From 523b5f4777d0ea7422fead1544de58fd870afa21 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 7 Jul 2017 17:52:53 +0200 Subject: [PATCH 01/14] server: smooth out btlog transfer for offline signing setups It turns out it is error prone to `git push` to a non-bare git repo. For the offline signing machine, the git remote needs to be a regular git repo in a directory on a thumbdrive so that once the thumbdrive is plugged into an online machine, that git repo can be transferred to the online machine. --- fdroidserver/server.py | 47 +++++++++++++++++++++++++++--------------- tests/run-tests | 32 +++++++++++++--------------- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/fdroidserver/server.py b/fdroidserver/server.py index 7ca6009a..ebfea3a3 100644 --- a/fdroidserver/server.py +++ b/fdroidserver/server.py @@ -507,7 +507,8 @@ def push_binary_transparency(git_repo_path, git_remote): If the remote is a local directory, make sure it exists, and is a git repo. This is used to move this git repo from an offline - machine onto a flash drive, then onto the online machine. + machine onto a flash drive, then onto the online machine. Also, + this pulls because pushing to a non-bare git repo is error prone. This is also used in offline signing setups, where it then also creates a "local copy dir" git repo that serves to shuttle the git @@ -518,24 +519,36 @@ def push_binary_transparency(git_repo_path, git_remote): ''' import git - if os.path.isdir(os.path.dirname(git_remote)) \ - and not os.path.isdir(os.path.join(git_remote, '.git')): - os.makedirs(git_remote, exist_ok=True) - repo = git.Repo.init(git_remote) - config = repo.config_writer() - config.set_value('receive', 'denyCurrentBranch', 'updateInstead') - config.release() - logging.info('Pushing binary transparency log to ' + git_remote) - gitrepo = git.Repo(git_repo_path) - origin = git.remote.Remote(gitrepo, 'origin') - if origin in gitrepo.remotes: - origin = gitrepo.remote('origin') - if 'set_url' in dir(origin): # added in GitPython 2.x - origin.set_url(git_remote) + + if os.path.isdir(os.path.dirname(git_remote)): + # from offline machine to thumbdrive + remote_path = os.path.abspath(git_repo_path) + if not os.path.isdir(os.path.join(git_remote, '.git')): + os.makedirs(git_remote, exist_ok=True) + thumbdriverepo = git.Repo.init(git_remote) + local = thumbdriverepo.create_remote('local', remote_path) + else: + thumbdriverepo = git.Repo(git_remote) + local = git.remote.Remote(thumbdriverepo, 'local') + if local in thumbdriverepo.remotes: + local = thumbdriverepo.remote('local') + if 'set_url' in dir(local): # force remote URL if using GitPython 2.x + local.set_url(remote_path) + else: + local = thumbdriverepo.create_remote('local', remote_path) + local.pull('master') else: - origin = gitrepo.create_remote('origin', git_remote) - origin.push('master') + # from online machine to remote on a server on the internet + gitrepo = git.Repo(git_repo_path) + origin = git.remote.Remote(gitrepo, 'origin') + if origin in gitrepo.remotes: + origin = gitrepo.remote('origin') + if 'set_url' in dir(origin): # added in GitPython 2.x + origin.set_url(git_remote) + else: + origin = gitrepo.create_remote('origin', git_remote) + origin.push('master') def main(): diff --git a/tests/run-tests b/tests/run-tests index eef54ee4..2cfdc55a 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -1051,24 +1051,20 @@ test `grep '' archive/index.xml | wc -l` -eq 2 cd binary_transparency [ `git rev-list --count HEAD` == "1" ] cd .. -if have_git_2_3; then - $fdroid server update --verbose - grep -F '> config.py - echo "sync_from_local_copy_dir = True" >> config.py - echo "serverwebroots = '$SERVERWEBROOT'" >> config.py - echo "servergitmirrors = '$SERVER_GIT_MIRROR'" >> config.py - echo "local_copy_dir = '$LOCAL_COPY_DIR'" >> config.py - echo "binary_transparency_remote = '$BINARY_TRANSPARENCY_REMOTE'" >> config.py - $fdroid server update --verbose - cd $BINARY_TRANSPARENCY_REMOTE - [ `git rev-list --count HEAD` == "1" ] - cd $SERVER_GIT_MIRROR - [ `git rev-list --count HEAD` == "1" ] -else - echo "Skipping test, `git --version` older than 2.3" -fi +$fdroid server update --verbose +grep -F '> config.py +echo "sync_from_local_copy_dir = True" >> config.py +echo "serverwebroots = '$SERVERWEBROOT'" >> config.py +echo "servergitmirrors = '$SERVER_GIT_MIRROR'" >> config.py +echo "local_copy_dir = '$LOCAL_COPY_DIR'" >> config.py +echo "binary_transparency_remote = '$BINARY_TRANSPARENCY_REMOTE'" >> config.py +$fdroid server update --verbose +cd $BINARY_TRANSPARENCY_REMOTE +[ `git rev-list --count HEAD` == "1" ] +cd $SERVER_GIT_MIRROR +[ `git rev-list --count HEAD` == "1" ] #------------------------------------------------------------------------------# From d8954fc033daa437f8a3882f1c163da2aa51e2d8 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 8 Jul 2017 12:11:42 +0200 Subject: [PATCH 02/14] update: force checkout .gitlab-ci.yml when updating git mirrors closes #309 --- fdroidserver/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdroidserver/server.py b/fdroidserver/server.py index ebfea3a3..0af5288d 100644 --- a/fdroidserver/server.py +++ b/fdroidserver/server.py @@ -393,7 +393,7 @@ def update_servergitmirrors(servergitmirrors, repo_section): if remote.name == 'gitlab': logging.debug('Removing .gitlab-ci.yml now that it has successfully deployed') repo.index.reset('HEAD^') - repo.index.checkout() + repo.index.checkout(force=True) if progress: bar.done() From 6d8e916491f9fc4d252d4249682ff63561b8aa13 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 10 Jul 2017 17:13:26 +0200 Subject: [PATCH 03/14] server: only rm git mirror if the git history is getting too large git hosts like github, gitlab, bitbucket usually allow 1 gig repos. This changes the git mirroring behavior to keep the history until the repo hits 1 gig. Keeping history makes updates a lot faster, since the whole repo does not need to be pushed on each update. --- fdroidserver/server.py | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/fdroidserver/server.py b/fdroidserver/server.py index 0af5288d..a4ae3c85 100644 --- a/fdroidserver/server.py +++ b/fdroidserver/server.py @@ -304,6 +304,16 @@ def update_localcopy(repo_section, local_copy_dir): push_binary_transparency(offline_copy, online_copy) +def _get_size(start_path='.'): + '''get size of all files in a dir https://stackoverflow.com/a/1392549''' + total_size = 0 + for dirpath, dirnames, filenames in os.walk(start_path): + for f in filenames: + fp = os.path.join(dirpath, f) + total_size += os.path.getsize(fp) + return total_size + + def update_servergitmirrors(servergitmirrors, repo_section): '''update repo mirrors stored in git repos @@ -327,13 +337,15 @@ def update_servergitmirrors(servergitmirrors, repo_section): if repo_section == 'repo': git_mirror_path = 'git-mirror' dotgit = os.path.join(git_mirror_path, '.git') - if not os.path.isdir(git_mirror_path): - os.mkdir(git_mirror_path) - elif os.path.isdir(dotgit): + git_repodir = os.path.join(git_mirror_path, 'fdroid', repo_section) + if not os.path.isdir(git_repodir): + os.makedirs(git_repodir) + if os.path.isdir(dotgit) and _get_size(git_mirror_path) > 1000000000: + logging.warning('Deleting git-mirror history, repo is too big (1 gig max)') shutil.rmtree(dotgit) - fdroid_repo_path = os.path.join(git_mirror_path, "fdroid") - _local_sync(repo_section, fdroid_repo_path) + # rsync is very particular about trailing slashes + _local_sync(repo_section.rstrip('/') + '/', git_repodir.rstrip('/') + '/') # use custom SSH command if identity_file specified ssh_cmd = 'ssh -oBatchMode=yes' @@ -344,10 +356,16 @@ def update_servergitmirrors(servergitmirrors, repo_section): repo = git.Repo.init(git_mirror_path) - for mirror in servergitmirrors: - hostname = re.sub(r'\W*\w+\W+(\w+).*', r'\1', mirror) - repo.create_remote(hostname, mirror) - logging.info('Mirroring to: ' + mirror) + for remote_url in servergitmirrors: + hostname = re.sub(r'\W*\w+\W+(\w+).*', r'\1', remote_url) + r = git.remote.Remote(repo, hostname) + if r in repo.remotes: + r = repo.remote(hostname) + if 'set_url' in dir(r): # force remote URL if using GitPython 2.x + r.set_url(remote_url) + else: + repo.create_remote(hostname, remote_url) + logging.info('Mirroring to: ' + remote_url) # sadly index.add don't allow the --all parameter logging.debug('Adding all files to git mirror') From 93caf27319da76626afef357b57c9e9fc7fd4622 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 12:59:20 +0200 Subject: [PATCH 04/14] server: include gitlab raw URLs as git mirrors gitlab serves raw files from a CDN, so its appropriate to use the raw URL. @pserwylo @grote and I discussed it and found a reference, but I can't find that reference now. Since the client will try the next mirror if one fails, it makes sense to include both the gitlab raw and gitlab pages URLs to the mirror. The gitlab pages deploy process is still a bit flaky anyway. --- fdroidserver/index.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/fdroidserver/index.py b/fdroidserver/index.py index 6843f520..86b4bb08 100644 --- a/fdroidserver/index.py +++ b/fdroidserver/index.py @@ -112,9 +112,8 @@ def make(apps, sortedids, apks, repodir, archive): else: mirrors.append(urllib.parse.urljoin(mirror + '/', urlbasepath)) for mirror in common.config.get('servergitmirrors', []): - mirror = get_mirror_service_url(mirror) - if mirror: - mirrors.append(mirror + '/' + repodir) + for url in get_mirror_service_urls(mirror): + mirrors.append(url + '/' + repodir) if mirrorcheckfailed: raise FDroidException("Malformed repository mirrors.") if mirrors: @@ -525,14 +524,15 @@ def extract_pubkey(): return hexlify(pubkey), repo_pubkey_fingerprint -def get_mirror_service_url(url): - '''Get direct URL from git service for use by fdroidclient +def get_mirror_service_urls(url): + '''Get direct URLs from git service for use by fdroidclient Via 'servergitmirrors', fdroidserver can create and push a mirror to certain well known git services like gitlab or github. This will always use the 'master' branch since that is the default - branch in git. - + branch in git. The files are then accessible via alternate URLs, + where they are served in their raw format via a CDN rather than + from git. ''' if url.startswith('git@'): @@ -549,18 +549,23 @@ def get_mirror_service_url(url): branch = "master" folder = "fdroid" + urls = [] if hostname == "github.com": - # Github-like RAW segments "https://raw.githubusercontent.com/user/repo/master/fdroid" + # Github-like RAW segments "https://raw.githubusercontent.com/user/repo/branch/folder" segments[2] = "raw.githubusercontent.com" segments.extend([branch, folder]) + urls.append('/'.join(segments)) elif hostname == "gitlab.com": - # Gitlab-like Pages segments "https://user.gitlab.com/repo/fdroid" - gitlab_url = ["https:", "", user + ".gitlab.io", repo, folder] - segments = gitlab_url - else: - return None + # Gitlab Raw "https://gitlab.com/user/repo/raw/branch/folder" + gitlab_raw = segments + ['raw', branch, folder] + urls.append('/'.join(gitlab_raw)) + # Gitlab-like Pages segments "https://user.gitlab.io/repo/folder" + gitlab_pages = ["https:", "", user + ".gitlab.io", repo, folder] + urls.append('/'.join(gitlab_pages)) + return urls + + return urls - return '/'.join(segments) def download_repo_index(url_str, etag=None, verify_fingerprint=True): From 1f7f9d403c193098df33467677e2fd6c48a0439f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 13:02:06 +0200 Subject: [PATCH 05/14] server: report errors pushing to git mirrors This makes `fdroid server update` fail if pushing to one of the git mirrors fails. This is what happens if the other methods fail, e.g. rsync or S3. closes #347 --- fdroidserver/index.py | 1 - fdroidserver/server.py | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/fdroidserver/index.py b/fdroidserver/index.py index 86b4bb08..b0de4325 100644 --- a/fdroidserver/index.py +++ b/fdroidserver/index.py @@ -567,7 +567,6 @@ def get_mirror_service_urls(url): return urls - def download_repo_index(url_str, etag=None, verify_fingerprint=True): """ Downloads the repository index from the given :param url_str diff --git a/fdroidserver/server.py b/fdroidserver/server.py index a4ae3c85..3b36ecee 100644 --- a/fdroidserver/server.py +++ b/fdroidserver/server.py @@ -386,7 +386,6 @@ def update_servergitmirrors(servergitmirrors, repo_section): # push for every remote. This will overwrite the git history for remote in repo.remotes: - branch = 'master' if remote.name == 'gitlab': logging.debug('Writing .gitlab-ci.yml to deploy to GitLab Pages') with open(os.path.join(git_mirror_path, ".gitlab-ci.yml"), "wt") as out_file: @@ -405,13 +404,16 @@ def update_servergitmirrors(servergitmirrors, repo_section): logging.debug('Pushing to ' + remote.url) with repo.git.custom_environment(GIT_SSH_COMMAND=ssh_cmd): - remote.push(branch, force=True, set_upstream=True, progress=progress) - - # Reset the gitlab specific stuff before the next remote. - if remote.name == 'gitlab': - logging.debug('Removing .gitlab-ci.yml now that it has successfully deployed') - repo.index.reset('HEAD^') - repo.index.checkout(force=True) + pushinfos = remote.push('master', force=True, set_upstream=True, progress=progress) + for pushinfo in pushinfos: + if pushinfo.flags & (git.remote.PushInfo.ERROR + | git.remote.PushInfo.REJECTED + | git.remote.PushInfo.REMOTE_FAILURE + | git.remote.PushInfo.REMOTE_REJECTED): + raise FDroidException(remote.url + ' push failed: ' + str(pushinfo.flags) + + ' ' + pushinfo.summary) + else: + logging.debug(remote.url + ': ' + pushinfo.summary) if progress: bar.done() From 2ecaf6ef8dc3e5c549907d55612caf98c8546050 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 15 Jul 2017 23:42:29 +0200 Subject: [PATCH 06/14] rewritemeta: only print file type if its changing --- fdroidserver/rewritemeta.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fdroidserver/rewritemeta.py b/fdroidserver/rewritemeta.py index 58fd7994..ae4627eb 100644 --- a/fdroidserver/rewritemeta.py +++ b/fdroidserver/rewritemeta.py @@ -77,8 +77,10 @@ def main(): if not options.to and ext not in supported: logging.info("Ignoring %s file at '%s'" % (ext, path)) continue - else: + elif options.to is not None: logging.info("rewriting '%s' to %s" % (appid, options.to)) + else: + logging.info("rewriting '%s'" % (appid)) to_ext = ext if options.to is not None: From 67d98c5a36025043d2f3875b52ca3a8837282dbd Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 15 Jul 2017 20:15:30 +0000 Subject: [PATCH 07/14] keep .apk file ext when diffoscope'ing Binaries: --- fdroidserver/build.py | 2 +- fdroidserver/publish.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fdroidserver/build.py b/fdroidserver/build.py index dff83104..3123a4ae 100644 --- a/fdroidserver/build.py +++ b/fdroidserver/build.py @@ -1158,7 +1158,7 @@ def main(): url = url.replace('%v', build.versionName) url = url.replace('%c', str(build.versionCode)) logging.info("...retrieving " + url) - of = common.get_release_filename(app, build) + '.binary' + of = re.sub(r'.apk$', '.binary.apk', common.get_release_filename(app, build)) of = os.path.join(output_dir, of) try: net.download_file(url, local_filename=of) diff --git a/fdroidserver/publish.py b/fdroidserver/publish.py index 4d92ebdd..1ca89e15 100644 --- a/fdroidserver/publish.py +++ b/fdroidserver/publish.py @@ -19,6 +19,7 @@ import sys import os +import re import shutil import glob import hashlib @@ -128,7 +129,7 @@ def main(): # version if everything checks out. # The binary should already have been retrieved during the build # process. - srcapk = apkfile + ".binary" + srcapk = re.sub(r'.apk$', '.binary.apk', apkfile) # Compare our unsigned one with the downloaded one... compare_result = common.verify_apks(srcapk, apkfile, tmp_dir) From 7613c18dd80969cec9db0e209611c9ebc3176fed Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 17 Jul 2017 12:11:33 +0200 Subject: [PATCH 08/14] verify: if downloading from /repo/ fails, try /archive/ The Builds entries in metadata/ files do not easily say whether a given APK is in the repo/ or the archive/. So it should also try to download the official APK from the archive/ when verifying. --- fdroidserver/verify.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fdroidserver/verify.py b/fdroidserver/verify.py index 966c3874..85d1d2b2 100644 --- a/fdroidserver/verify.py +++ b/fdroidserver/verify.py @@ -80,7 +80,10 @@ def main(): try: net.download_file(url, dldir=tmp_dir) except requests.exceptions.HTTPError as e: - raise FDroidException('Downloading %s failed. %s', (url, e)) + try: + net.download_file(url.replace('/repo', '/archive/'), dldir=tmp_dir) + except requests.exceptions.HTTPError as e: + raise FDroidException('Downloading %s failed. %s', (url, e)) compare_result = common.verify_apks( remoteapk, From 3e67634a276b4f40b136cfb1a89751adbf92b55c Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 09:55:45 +0200 Subject: [PATCH 09/14] wp-droid: move deprecated Wordpress plugin to its own repo closes #325 --- MANIFEST.in | 5 - wp-fdroid/AndroidManifest.xml | 2711 ----------------------- wp-fdroid/android-permissions.php | 114 - wp-fdroid/readme.txt | 34 - wp-fdroid/strings.xml | 3389 ----------------------------- wp-fdroid/wp-fdroid.php | 1017 --------- 6 files changed, 7270 deletions(-) delete mode 100644 wp-fdroid/AndroidManifest.xml delete mode 100644 wp-fdroid/android-permissions.php delete mode 100644 wp-fdroid/readme.txt delete mode 100644 wp-fdroid/strings.xml delete mode 100644 wp-fdroid/wp-fdroid.php diff --git a/MANIFEST.in b/MANIFEST.in index 320ffe47..a5945d70 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -26,8 +26,3 @@ include tests/run-tests include tests/update.TestCase include tests/urzip.apk include tests/urzip-badsig.apk -include wp-fdroid/AndroidManifest.xml -include wp-fdroid/android-permissions.php -include wp-fdroid/readme.txt -include wp-fdroid/strings.xml -include wp-fdroid/wp-fdroid.php diff --git a/wp-fdroid/AndroidManifest.xml b/wp-fdroid/AndroidManifest.xml deleted file mode 100644 index 83559288..00000000 --- a/wp-fdroid/AndroidManifest.xml +++ /dev/null @@ -1,2711 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wp-fdroid/android-permissions.php b/wp-fdroid/android-permissions.php deleted file mode 100644 index c59bc6d4..00000000 --- a/wp-fdroid/android-permissions.php +++ /dev/null @@ -1,114 +0,0 @@ -android_manifest_file_path = $android_manifest_file_path_in; - $this->android_strings_file_path = $android_strings_file_path_in; - $this->cache_file_path = $cache_file_path_in; - } - - // Returns an associative array with android permissions and data about them - function get_permissions_array() { - - // Check status of cache - $android_manifest_file_stat = stat($this->android_manifest_file_path); - $android_manifest_file_mtime = $android_manifest_file_stat['mtime']; - $android_strings_file_stat = stat($this->android_strings_file_path); - $android_strings_file_mtime = $android_strings_file_stat['mtime']; - $cache_file_mtime = 0; - if(file_exists($this->cache_file_path)) { - $cache_file_stat = stat($this->cache_file_path); - $cache_file_mtime = $cache_file_stat['mtime']; - } - - // If the cache is fresh, use it instead - if($android_manifest_file_mtime < $cache_file_mtime && $android_strings_file_mtime < $cache_file_mtime ) { - $cache_file_handle = fopen($this->cache_file_path, 'r'); - $cache_file_content = fread($cache_file_handle, filesize($this->cache_file_path)); - fclose($cache_file_handle); - - $permissions = unserialize($cache_file_content); - - return $permissions; - } - - // We are updating the cache, touch the file (note: race condition possible between stating the cache file above and this line...) - touch($this->cache_file_path); - - // Get permission raw data from XML - $manifestDoc = new DOMDocument; - $manifestDoc->load($this->android_manifest_file_path); - $manifestXpath = new DOMXPath($manifestDoc); - - $stringsDoc = new DOMDocument; - $stringsDoc->load($this->android_strings_file_path); - $stringsXpath = new DOMXPath($stringsDoc); - - $comment = ''; - foreach ($manifestXpath->query('node()') as $node) { - // Save permissions and permission groups from tags - if($node->nodeName == 'permission-group' || $node->nodeName == 'permission') { - $name = $node->attributes->getNamedItem('name')->value; - $name = substr(strrchr($name,'.'), 1); - - // Lookup the human readable title - $labelObject = $node->attributes->getNamedItem('label'); - $labelString = $name; - if( $labelObject !== NULL ) { - $labelName = substr(strrchr($labelObject->value,'/'),1); - $labelStringObject = $stringsXpath->query('//string[@name="'.$labelName.'"]'); - $labelString = ucfirst($labelStringObject->item(0)->nodeValue); - } - - // Lookup the human readable description - $descriptionObject = $node->attributes->getNamedItem('description'); - $descriptionString = '(Description missing)'; - if($descriptionObject !== NULL) { - $descriptionName = substr(strrchr($descriptionObject->value,'/'),1); - $descriptionStringObject = $stringsXpath->query('//string[@name="'.$descriptionName.'"]'); - $descriptionString = ucfirst($descriptionStringObject->item(0)->nodeValue); - } - - $permissions[$node->nodeName][$name]['label'] = stripslashes($labelString); - $permissions[$node->nodeName][$name]['description'] = stripslashes($descriptionString); - $permissions[$node->nodeName][$name]['comment'] = stripslashes(str_replace(array("\r\n", "\r", "\n", "\t", ' '), '', $comment)); - - if($node->nodeName == 'permission') { - $permissionGroupObject = $node->attributes->getNamedItem('permissionGroup'); - $permissionGroup = 'none'; - if($permissionGroupObject !== NULL) { - $permissionGroup = substr(strrchr($permissionGroupObject->value,'.'), 1); - } - - $permissions[$node->nodeName][$name]['permissionGroup'] = $permissionGroup; - $permissions[$node->nodeName][$name]['protectionLevel'] = $node->attributes->getNamedItem('protectionLevel')->value; - } - } - - // Cache descriptions from comments preceding the tags - if($node->nodeName == '#comment') { - $comment .= $node->textContent; - } - elseif($node->nodeName != '#text') { - $comment = ''; - } - } - - // Update cache with serialized permissions - $cache_file_handle = fopen($this->cache_file_path, 'w'); - fwrite($cache_file_handle, serialize($permissions)); - fclose($cache_file_handle); - - return $permissions; - } -} -?> diff --git a/wp-fdroid/readme.txt b/wp-fdroid/readme.txt deleted file mode 100644 index 0dfba563..00000000 --- a/wp-fdroid/readme.txt +++ /dev/null @@ -1,34 +0,0 @@ - -=== WP FDroid === -Contributors: CiaranG -Tags: android, repository -Requires at least: 2.9 -Tested up to: 2.9 -Stable tag: 0.1 - -Provides the ability to browse the contents of an FDroid repository. - -== Description == - -This plugin provides the ability to browse the contents of an FDroid -repository. The repository browser can be inserted into the site by -creating a page containing the 'fdroidrepo' shortcode. - -License: GPL v3 - -== Installation == - -1. Download and extract the zip file. -2. Upload the plugin directory to /wp-content/plugins on your server. -3. Go to the Plugins screen in your Wordpress Admin and activate it. - -== Frequently Asked Questions == - -= Is this finished? = - -No it isn't. I'm working on it. - -== Screenshots == - -1. There isn't one yet actually. - diff --git a/wp-fdroid/strings.xml b/wp-fdroid/strings.xml deleted file mode 100644 index 7b785ec5..00000000 --- a/wp-fdroid/strings.xml +++ /dev/null @@ -1,3389 +0,0 @@ - - - - - B - - KB - - MB - - GB - - TB - - PB - - %1$s%2$s - - - <untitled> - - - \u2026 - - - \u2025 - - - (No phone number) - - - (Unknown) - - - Voicemail - - - MSISDN1 - - - - Connection problem or invalid MMI code. - - Operation is restricted to fixed dialing numbers only. - - - Service was enabled. - - Service was enabled for: - - Service has been disabled. - - Registration was successful. - - Erasure was successful. - - Incorrect password. - - MMI complete. - - The old PIN you typed is not correct. - - The PUK you typed is not correct. - - The PINs you entered do not match. - - Type a PIN that is 4 to 8 numbers. - - Type a PUK that is 8 numbers or longer. - - Your SIM card is PUK-locked. Type the PUK code to unlock it. - Type PUK2 to unblock SIM card. - - - Incoming Caller ID - - Outgoing Caller ID - - Call forwarding - - Call waiting - - Call barring - - Password change - - PIN change - Calling number present - Calling number restricted - Three way calling - Rejection of undesired annoying calls - Calling number delivery - Do not disturb - - - Caller ID defaults to restricted. Next call: Restricted - - Caller ID defaults to restricted. Next call: Not restricted - - Caller ID defaults to not restricted. Next call: Restricted - - Caller ID defaults to not restricted. Next call: Not restricted - - - - Service not provisioned. - - The caller ID setting cannot be changed. - - - Restricted access changed - - Data service is blocked. - - Emergency service is blocked. - - Voice service is blocked. - - All Voice services are blocked. - - SMS service is blocked. - - Voice/Data services are blocked. - - Voice/SMS services are blocked. - - All Voice/Data/SMS services are blocked. - - - - Voice - - Data - - FAX - - SMS - - Async - - Sync - - Packet - - PAD - - - - Roaming Indicator On - Roaming Indicator Off - Roaming Indicator Flashing - Out of Neighborhood - Out of Building - Roaming - Preferred System - Roaming - Available System - Roaming - Alliance Partner - Roaming - Premium Partner - Roaming - Full Service Functionality - Roaming - Partial Service Functionality - Roaming Banner On - Roaming Banner Off - Searching for Service - - - - - {0}: Not forwarded - - {0}: {1} - - {0}: {1} after {2} seconds - - {0}: Not forwarded - - {0}: Not forwarded - - - - Feature code complete. - - Connection problem or invalid feature code. - - - OK - - A network error occurred. - - The URL could not be found. - - The site authentication scheme is not supported. - - Authentication was unsuccessful. - - Authentication via the proxy server was unsuccessful. - - The connection to the server was unsuccessful. - - The server couldn\'t communicate. Try again later. - - The connection to the server timed out. - - The page contains too many server redirects. - - The protocol is not supported. - - A secure connection could not be established. - - The page could not be opened because the URL is invalid. - - The file could not be accessed. - - The requested file was not found. - - Too many requests are being processed. Try again later. - - - - Sign-in error for %1$s - - - - Sync - - Sync - - Too many %s deletes. - - - Tablet storage is full! Delete some files to free space. - - Phone storage is full! Delete some files to free space. - - - - Me - - - - Tablet options - - Phone options - - Silent mode - - Turn on wireless - - Turn off wireless - - Screen lock - - Power off - - Ringer off - - Ringer vibrate - - Ringer on - - - Shutting down\u2026 - - - Your tablet will shut down. - - Your phone will shut down. - - - Would you like to shut down? - - - Recent - - No recent applications. - - - Tablet options - - Phone options - - - Screen lock - - - Power off - - - Silent mode - - - Sound is OFF - - - Sound is ON - - - Airplane mode - - - Airplane mode is ON - - - Airplane mode is OFF - - - 999+ - - - Safe mode - - - Android System - - - Services that cost you money - - Allow applications to do things - that can cost you money. - - - Your messages - - Read and write your SMS, - e-mail, and other messages. - - - Your personal information - - Direct access to your contacts - and calendar stored on the tablet. - - Direct access to your contacts - and calendar stored on the phone. - - - Your location - - Monitor your physical location - - - Network communication - - Allow applications to access - various network features. - - - Your accounts - - Access the available accounts. - - - Hardware controls - - Direct access to hardware on - the handset. - - - Phone calls - - Monitor, record, and process - phone calls. - - - System tools - - Lower-level access and control - of the system. - - - Development tools - - Features only needed for - application developers. - - - Storage - - Access the USB storage. - - Access the SD card. - - - - - disable or modify status bar - - Allows application to disable - the status bar or add and remove system icons. - - - status bar - - Allows the application to be the status bar. - - - expand/collapse status bar - - Allows application to - expand or collapse the status bar. - - - intercept outgoing calls - - Allows application to - process outgoing calls and change the number to be dialed. Malicious - applications may monitor, redirect, or prevent outgoing calls. - - - receive SMS - - Allows application to receive - and process SMS messages. Malicious applications may monitor - your messages or delete them without showing them to you. - - - receive MMS - - Allows application to receive - and process MMS messages. Malicious applications may monitor - your messages or delete them without showing them to you. - - - receive emergency broadcasts - - Allows application to receive - and process emergency broadcast messages. This permission is only available - to system applications. - - - send SMS messages - - Allows application to send SMS - messages. Malicious applications may cost you money by sending - messages without your confirmation. - - - send SMS messages with no confirmation - - Allows application to send SMS - messages. Malicious applications may cost you money by sending - messages without your confirmation. - - - read SMS or MMS - - Allows application to read - SMS messages stored on your tablet or SIM card. Malicious applications - may read your confidential messages. - - Allows application to read - SMS messages stored on your phone or SIM card. Malicious applications - may read your confidential messages. - - - edit SMS or MMS - - Allows application to write - to SMS messages stored on your tablet or SIM card. Malicious applications - may delete your messages. - - Allows application to write - to SMS messages stored on your phone or SIM card. Malicious applications - may delete your messages. - - - receive WAP - - Allows application to receive - and process WAP messages. Malicious applications may monitor - your messages or delete them without showing them to you. - - - retrieve running applications - - Allows application to retrieve - information about currently and recently running tasks. May allow - malicious applications to discover private information about other applications. - - - reorder running applications - - Allows an application to move - tasks to the foreground and background. Malicious applications can force - themselves to the front without your control. - - - stop running applications - - Allows an application to remove - tasks and kill their applications. Malicious applications can disrupt - the behavior of other applications. - - - enable application debugging - - Allows an application to turn - on debugging for another application. Malicious applications can use this - to kill other applications. - - - change your UI settings - - Allows an application to - change the current configuration, such as the locale or overall font - size. - - - enable car mode - - Allows an application to - enable the car mode. - - - kill background processes - - Allows an application to - kill background processes of other applications, even if memory - isn\'t low. - - - force stop other applications - - Allows an application to - forcibly stop other applications. - - - force application to close - - Allows an application to force any - activity that is in the foreground to close and go back. - Should never be needed for normal applications. - - - retrieve system internal state - - Allows application to retrieve - internal state of the system. Malicious applications may retrieve - a wide variety of private and secure information that they should - never normally need. - - - retrieve screen content - - Allows application to retrieve - the content of the active window. Malicious applications may retrieve - the entire window content and examine all its text except passwords. - - - partial shutdown - - Puts the activity manager into a shutdown - state. Does not perform a complete shutdown. - - - prevent app switches - - Prevents the user from switching to - another application. - - - monitor and control all application launching - - Allows an application to - monitor and control how the system launches activities. - Malicious applications may completely compromise the system. This - permission is only needed for development, never for normal - use. - - - send package removed broadcast - - Allows an application to - broadcast a notification that an application package has been removed. - Malicious applications may use this to kill any other running - application. - - - send SMS-received broadcast - - Allows an application to - broadcast a notification that an SMS message has been received. - Malicious applications may use this to forge incoming SMS messages. - - - send WAP-PUSH-received broadcast - - Allows an application to - broadcast a notification that a WAP PUSH message has been received. - Malicious applications may use this to forge MMS message receipt or to - silently replace the content of any web page with malicious variants. - - - limit number of running processes - - Allows an application - to control the maximum number of processes that will run. Never - needed for normal applications. - - - make all background applications close - - Allows an application - to control whether activities are always finished as soon as they - go to the background. Never needed for normal applications. - - - modify battery statistics - - Allows the modification of - collected battery statistics. Not for use by normal applications. - - - control system backup and restore - - Allows the application to control the system\'s backup and restore mechanism. Not for use by normal applications. - - - confirm a full backup or restore operation - - Allows the application to launch the full backup confirmation UI. Not to be used by any application. - - - display unauthorized windows - - Allows the creation of - windows that are intended to be used by the internal system - user interface. Not for use by normal applications. - - - display system-level alerts - - Allows an application to - show system alert windows. Malicious applications can take over the - entire screen. - - - modify global animation speed - - Allows an application to change - the global animation speed (faster or slower animations) at any time. - - - manage application tokens - - Allows applications to - create and manage their own tokens, bypassing their normal - Z-ordering. Should never be needed for normal applications. - - - press keys and control buttons - - Allows an application to deliver - its own input events (key presses, etc.) to other applications. Malicious - applications can use this to take over the tablet. - - Allows an application to deliver - its own input events (key presses, etc.) to other applications. Malicious - applications can use this to take over the phone. - - - record what you type and actions you take - - Allows applications to watch the - keys you press even when interacting with another application (such - as entering a password). Should never be needed for normal applications. - - - bind to an input method - - Allows the holder to bind to the top-level - interface of an input method. Should never be needed for normal applications. - - - bind to a text service - - Allows the holder to bind to the top-level - interface of a text service(e.g. SpellCheckerService). Should never be needed for normal applications. - - - bind to a VPN service - - Allows the holder to bind to the top-level - interface of a Vpn service. Should never be needed for normal applications. - - - bind to a wallpaper - - Allows the holder to bind to the top-level - interface of a wallpaper. Should never be needed for normal applications. - - - bind to a widget service - - Allows the holder to bind to the top-level - interface of a widget service. Should never be needed for normal applications. - - - interact with a device admin - - Allows the holder to send intents to - a device administrator. Should never be needed for normal applications. - - - change screen orientation - - Allows an application to change - the rotation of the screen at any time. Should never be needed for - normal applications. - - - change pointer speed - - Allows an application to change - the mouse or trackpad pointer speed at any time. Should never be needed for - normal applications. - - - send Linux signals to applications - - Allows application to request that the - supplied signal be sent to all persistent processes. - - - make application always run - - Allows an application to make - parts of itself persistent, so the system can\'t use it for other - applications. - - - delete applications - - Allows an application to delete - Android packages. Malicious applications can use this to delete important applications. - - - delete other applications\' data - - Allows an application to clear user data. - - delete other applications\' caches - - Allows an application to delete - cache files. - - - measure application storage space - - Allows an application to retrieve - its code, data, and cache sizes - - - directly install applications - - Allows an application to install new or updated - Android packages. Malicious applications can use this to add new applications with arbitrarily - powerful permissions. - - - delete all application cache data - - Allows an application to free tablet storage - by deleting files in application cache directory. Access is very - restricted usually to system process. - - Allows an application to free phone storage - by deleting files in application cache directory. Access is very - restricted usually to system process. - - - Move application resources - - Allows an application to move application resources from internal to external media and vice versa. - - - read sensitive log data - - Allows an application to read from the - system\'s various log files. This allows it to discover general - information about what you are doing with the tablet, potentially - including personal or private information. - - Allows an application to read from the - system\'s various log files. This allows it to discover general - information about what you are doing with the phone, potentially - including personal or private information. - - - use any media decoder for playback - - Allows an application to use any installed - media decoder to decode for playback. - - - read/write to resources owned by diag - - Allows an application to read and write to - any resource owned by the diag group; for example, files in /dev. This could - potentially affect system stability and security. This should be ONLY be used - for hardware-specific diagnostics by the manufacturer or operator. - - - enable or disable application components - - Allows an application to change whether a - component of another application is enabled or not. Malicious applications can use this - to disable important tablet capabilities. Care must be used with this permission, as it is - possible to get application components into an unusable, inconsistent, or unstable state. - - - Allows an application to change whether a - component of another application is enabled or not. Malicious applications can use this - to disable important phone capabilities. Care must be used with this permission, as it is - possible to get application components into an unusable, inconsistent, or unstable state. - - - - set preferred applications - - Allows an application to - modify your preferred applications. This can allow malicious applications - to silently change the applications that are run, spoofing your - existing applications to collect private data from you. - - - modify global system settings - - Allows an application to modify the - system\'s settings data. Malicious applications can corrupt your system\'s - configuration. - - modify secure system settings - Allows an application to modify the - system\'s secure settings data. Not for use by normal applications. - - - modify the Google services map - - Allows an application to modify the - Google services map. Not for use by normal applications. - - - automatically start at boot - - Allows an application to - have itself started as soon as the system has finished booting. - This can make it take longer to start the tablet and allow the - application to slow down the overall tablet by always running. - - Allows an application to - have itself started as soon as the system has finished booting. - This can make it take longer to start the phone and allow the - application to slow down the overall phone by always running. - - - send sticky broadcast - - Allows an application to send - sticky broadcasts, which remain after the broadcast ends. - Malicious applications can make the tablet slow or unstable by causing it - to use too much memory. - - Allows an application to send - sticky broadcasts, which remain after the broadcast ends. - Malicious applications can make the phone slow or unstable by causing it - to use too much memory. - - - read contact data - - Allows an application to read all - of the contact (address) data stored on your tablet. Malicious applications - can use this to send your data to other people. - - Allows an application to read all - of the contact (address) data stored on your phone. Malicious applications - can use this to send your data to other people. - - - write contact data - - Allows an application to modify the - contact (address) data stored on your tablet. Malicious - applications can use this to erase or modify your contact data. - - Allows an application to modify the - contact (address) data stored on your phone. Malicious - applications can use this to erase or modify your contact data. - - - read your profile data - - Allows the application to read personal - profile information stored on your device, such as your name and contact information. This - means the application can identify you and send your profile information to others. - - - write to your profile data - - Allows the application to change or add - to personal profile information stored on your device, such as your name and contact - information. This means other applications can identify you and send your profile - information to others. - - - read your social stream - Allows the application to access - and sync social updates from you and your friends. Malicious apps can use this to read - private communications between you and your friends on social networks. - - - write to your social stream - Allows the application to display - social updates from your friends. Malicious apps can use this to pretend to be a friend - and trick you into revealing passwords or other confidential information. - - - - read calendar events plus confidential information - - Allows an application to read all calendar - events stored on your tablet, including those of friends or coworkers. A malicious application with - this permission can extract personal information from these calendars without the owners\' knowledge. - - Allows an application to read all calendar - events stored on your phone, including those of friends or coworkers. A malicious application with - this permission can extract personal information from these calendars without the owners\' knowledge. - - - add or modify calendar events and send email to guests without owners\' knowledge - - Allows an application to send event invitations as the calendar owner and add, remove, - change events that you can modify on your device, including those of friends or co-workers. A malicious application with this permission - can send spam emails that appear to come from calendar owners, modify events without the owners\' knowledge, or add fake events. - - - mock location sources for testing - - Create mock location sources for testing. - Malicious applications can use this to override the location and/or status returned by real - location sources such as GPS or Network providers. - - - access extra location provider commands - - Access extra location provider commands. - Malicious applications could use this to interfere with the operation of the GPS - or other location sources. - - - permission to install a location provider - - Create mock location sources for testing. - Malicious applications can use this to override the location and/or status returned by real - location sources such as GPS or Network providers or monitor and report your location to an external source. - - - fine (GPS) location - - Access fine location sources such as the - Global Positioning System on the tablet, where available. - Malicious applications can use this to determine where you are, and may - consume additional battery power. - - Access fine location sources such as the - Global Positioning System on the phone, where available. - Malicious applications can use this to determine where you are, and may - consume additional battery power. - - - coarse (network-based) location - - Access coarse location sources such as the cellular - network database to determine an approximate tablet location, where available. Malicious - applications can use this to determine approximately where you are. - - Access coarse location sources such as the cellular - network database to determine an approximate phone location, where available. Malicious - applications can use this to determine approximately where you are. - - - access SurfaceFlinger - - Allows application to use - SurfaceFlinger low-level features. - - - read frame buffer - - Allows application to - read the content of the frame buffer. - - - change your audio settings - - Allows application to modify - global audio settings such as volume and routing. - - - record audio - - Allows application to access - the audio record path. - - - take pictures and videos - - Allows application to take pictures and videos - with the camera. This allows the application at any time to collect - images the camera is seeing. - - - permanently disable tablet - - permanently disable phone - - Allows the application to - disable the entire tablet permanently. This is very dangerous. - - Allows the application to - disable the entire phone permanently. This is very dangerous. - - - force tablet reboot - - force phone reboot - - Allows the application to - force the tablet to reboot. - - Allows the application to - force the phone to reboot. - - - mount and unmount filesystems - - Allows the application to mount and - unmount filesystems for removable storage. - - - format external storage - - Allows the application to format removable storage. - - - get information on internal storage - - Allows the application to get information on internal storage. - - - create internal storage - - Allows the application to create internal storage. - - - destroy internal storage - - Allows the application to destroy internal storage. - - - mount / unmount internal storage - - Allows the application to mount / unmount internal storage. - - - rename internal storage - - Allows the application to rename internal storage. - - - control vibrator - - Allows the application to control - the vibrator. - - - control flashlight - - Allows the application to control - the flashlight. - - - manage preferences and permissions for USB devices - - Allows the application to manage preferences and permissions for USB devices. - - - implement MTP protocol - - Allows access to the kernel MTP driver to implement the MTP USB protocol. - - - test hardware - - Allows the application to control - various peripherals for the purpose of hardware testing. - - - directly call phone numbers - - Allows the application to call - phone numbers without your intervention. Malicious applications may - cause unexpected calls on your phone bill. Note that this does not - allow the application to call emergency numbers. - - - directly call any phone numbers - - Allows the application to call - any phone number, including emergency numbers, without your intervention. - Malicious applications may place unnecessary and illegal calls to emergency - services. - - - directly start CDMA tablet setup - - directly start CDMA phone setup - - Allows the application to start CDMA provisioning. - Malicious applications may unnecessarily start CDMA provisioning - - - control location update notifications - - Allows enabling/disabling location - update notifications from the radio. Not for use by normal applications. - - - access checkin properties - - Allows read/write access to - properties uploaded by the checkin service. Not for use by normal - applications. - - - choose widgets - - Allows the application to tell the system - which widgets can be used by which application. With this permission, - applications can give access to personal data to other applications. - Not for use by normal applications. - - - modify phone state - - Allows the application to control the - phone features of the device. An application with this permission can switch - networks, turn the phone radio on and off and the like without ever notifying - you. - - - read phone state and identity - - Allows the application to access the phone - features of the device. An application with this permission can determine the phone - number and serial number of this phone, whether a call is active, the number that call - is connected to and the like. - - - prevent tablet from sleeping - - prevent phone from sleeping - - Allows an application to prevent - the tablet from going to sleep. - - Allows an application to prevent - the phone from going to sleep. - - - power tablet on or off - - power phone on or off - - Allows the application to turn the - tablet on or off. - - Allows the application to turn the - phone on or off. - - - run in factory test mode - - Run as a low-level manufacturer test, - allowing complete access to the tablet hardware. Only available - when a tablet is running in manufacturer test mode. - - Run as a low-level manufacturer test, - allowing complete access to the phone hardware. Only available - when a phone is running in manufacturer test mode. - - - set wallpaper - - Allows the application - to set the system wallpaper. - - - set wallpaper size hints - - Allows the application - to set the system wallpaper size hints. - - - reset system to factory defaults - - Allows an application to completely - reset the system to its factory settings, erasing all data, - configuration, and installed applications. - - - set time - - Allows an application to change - the tablet\'s clock time. - - Allows an application to change - the phone\'s clock time. - - - set time zone - - Allows an application to change - the tablet\'s time zone. - - Allows an application to change - the phone\'s time zone. - - - act as the AccountManagerService - - Allows an - application to make calls to AccountAuthenticators - - - discover known accounts - - Allows an application to get - the list of accounts known by the tablet. - - Allows an application to get - the list of accounts known by the phone. - - - act as an account authenticator - - Allows an application - to use the account authenticator capabilities of the - AccountManager, including creating accounts and getting and - setting their passwords. - - - manage the accounts list - - Allows an application to - perform operations like adding, and removing accounts and deleting - their password. - - - use the authentication - credentials of an account - - Allows an application to - request authentication tokens. - - - view network state - - Allows an application to view - the state of all networks. - - - full Internet access - - Allows an application to - create network sockets. - - - change/intercept network settings and traffic - - Allows an application to change network settings and to intercept and inspect all network traffic, - for example to change the proxy and port of any APN. Malicious applications could monitor, redirect, or modify network - packets without your knowledge. - - - change network connectivity - - Allows an application to change - the state of network connectivity. - - - Change tethered connectivity - - Allows an application to change - the state of tethered network connectivity. - - - change background data usage setting - - Allows an application to change - the background data usage setting. - - - view Wi-Fi state - - Allows an application to view - the information about the state of Wi-Fi. - - - change Wi-Fi state - - Allows an application to connect - to and disconnect from Wi-Fi access points, and to make changes to - configured Wi-Fi networks. - - - allow Wi-Fi Multicast - reception - - Allows an application to - receive packets not directly addressed to your device. This can be - useful when discovering services offered near by. It uses more power - than the non-multicast mode. - - - view WiMAX state - Allows an application to view - the information about the state of WiMAX. - change WiMAX state - Allows an application to connect - to and disconnect from WiMAX network. - bluetooth administration - - Allows an application to configure - the local Bluetooth tablet, and to discover and pair with remote - devices. - - Allows an application to configure - the local Bluetooth phone, and to discover and pair with remote - devices. - - - create Bluetooth connections - - Allows an application to view - configuration of the local Bluetooth tablet, and to make and accept - connections with paired devices. - - Allows an application to view - configuration of the local Bluetooth phone, and to make and accept - connections with paired devices. - - - control Near Field Communication - - Allows an application to communicate - with Near Field Communication (NFC) tags, cards, and readers. - - - disable keylock - - Allows an application to disable - the keylock and any associated password security. A legitimate example of - this is the phone disabling the keylock when receiving an incoming phone call, - then re-enabling the keylock when the call is finished. - - - read sync settings - - Allows an application to read the sync settings, - such as whether sync is enabled for Contacts. - - - write sync settings - - Allows an application to modify the sync - settings, such as whether sync is enabled for Contacts. - - - read sync statistics - - Allows an application to read the sync stats; e.g., the - history of syncs that have occurred. - - - read subscribed feeds - - Allows an application to get details about the currently synced feeds. - - - write subscribed feeds - - Allows an application to modify - your currently synced feeds. This could allow a malicious application to - change your synced feeds. - - - read user defined dictionary - - Allows an application to read any private - words, names and phrases that the user may have stored in the user dictionary. - - - write to user defined dictionary - - Allows an application to write new words into the - user dictionary. - - - modify/delete USB storage contents - - modify/delete SD card contents - - Allows an application to write to the USB storage. - - Allows an application to write to the SD card. - - - modify/delete internal media storage contents - - Allows an application to modify the contents of the internal media storage. - - - access the cache filesystem - - Allows an application to read and write the cache filesystem. - - - make/receive Internet calls - - Allows an application to use the SIP service to make/receive Internet calls. - - - read historical network usage - - Allows an application to read historical network usage for specific networks and applications. - - - manage network policy - - Allows an application to manage network policies and define application-specific rules. - - - modify network usage accounting - - Allows modification of how network usage is accounted against applications. Not for use by normal applications. - - - - - Set password rules - - Control the length and the characters - allowed in screen-unlock passwords - - Monitor screen-unlock attempts - - Monitor the number of incorrect passwords - entered when unlocking the screen, and lock the tablet or erase all the tablet\'s - data if too many incorrect passwords are entered - - Monitor the number of incorrect passwords - entered when unlocking the screen, and lock the phone or erase all the phone\'s - data if too many incorrect passwords are entered - - Change the screen-unlock password - - Change the screen-unlock password - - Lock the screen - - Control how and when the screen locks - - Erase all data - - Erase the tablet\'s data without warning, - by performing a factory data reset - - Erase the phone\'s data without warning, - by performing a factory data reset - Set the device global proxy - - Set the device global proxy - to be used while policy is enabled. Only the first device admin - sets the effective global proxy. - - Set lock-screen password expiration - - Control how frequently the lock-screen password must be - changed - - Set storage encryption - - Require that stored application data be encrypted - - - Disable cameras - - Prevent use of all device cameras - - - - - Home - Mobile - Work - Work Fax - Home Fax - Pager - Other - Custom - - - - - - Home - Work - Other - Custom - - - - - - Home - Work - Other - Custom - - - - - - Home - Work - Other - Custom - - - - - - Work - Other - Custom - - - - - - AIM - Windows Live - Yahoo - Skype - QQ - Google Talk - ICQ - Jabber - - - - Custom - - Home - - Mobile - - Work - - Work Fax - - Home Fax - - Pager - - Other - - Callback - - Car - - Company Main - - ISDN - - Main - - Other Fax - - Radio - - Telex - - TTY TDD - - Work Mobile - - Work Pager - - Assistant - - MMS - - - Custom - - Birthday - - Anniversary - - Other - - - Custom - - Home - - Work - - Other - - Mobile - - - Custom - - Home - - Work - - Other - - - Custom - - Home - - Work - - Other - - - Custom - - AIM - - Windows Live - - Yahoo - - Skype - - QQ - - Google Talk - - ICQ - - Jabber - - NetMeeting - - - Work - - Other - - Custom - - - Custom - - Assistant - - Brother - - Child - - Domestic Partner - - Father - - Friend - - Manager - - Mother - - Parent - - Partner - - Referred by - - Relative - - Sister - - Spouse - - - Custom - - Home - - Work - - Other - - - Enter PIN code - - - Enter PUK and new PIN code - - - PUK code - - New Pin Code - - - Touch to enter password - - - Enter password to unlock - - - Enter PIN to unlock - - - Incorrect PIN code! - - - To unlock, press Menu then 0. - - - Emergency number - - - - - No service. - - - Screen locked. - - - Press Menu to unlock or place emergency call. - - - Press Menu to unlock. - - - Draw pattern to unlock - - Emergency call - - Return to call - - Correct! - - Sorry, try again - - Sorry, try again - - - Charging, %d%% - - Charged. - - %d%% - - - Connect your charger. - - - No SIM card. - - No SIM card in tablet. - - No SIM card in phone. - - Please insert a SIM card. - - The SIM card is missing or not readable. Please insert a SIM card. - - Your SIM card is permanently disabled.\n - Please contact your wireless service provider to obtain another SIM card. - - - Previous track button - - Next track button - - Pause button - - Play button - - Stop button - - - Emergency calls only - - - Network locked - - - - SIM card is PUK-locked. - - Please see the User Guide or contact Customer Care. - - - SIM card is locked. - - - Unlocking SIM card\u2026 - - - - You have incorrectly drawn your unlock pattern %d times. - \n\nPlease try again in %d seconds. - - - - - You have incorrectly entered your password %d times. - \n\nPlease try again in %d seconds. - - - - - You have incorrectly entered your PIN %d times. - \n\nPlease try again in %d seconds. - - - - - You have incorrectly drawn your unlock pattern %d times. - After %d more unsuccessful attempts, - you will be asked to unlock your tablet using your Google sign-in.\n\n - Please try again in %d seconds. - - - - - You have incorrectly drawn your unlock pattern %d times. - After %d more unsuccessful attempts, - you will be asked to unlock your phone using your Google sign-in.\n\n - Please try again in %d seconds. - - - - - You have incorrectly attempted to unlock the tablet %d times. - After %d more unsuccessful attempts, - the tablet will be reset to factory default and all user data will be lost. - - - - - You have incorrectly attempted to unlock the phone %d times. - After %d more unsuccessful attempts, - the phone will be reset to factory default and all user data will be lost. - - - - - You have incorrectly attempted to unlock the tablet %d times. - The tablet will now be reset to factory default. - - - - - You have incorrectly attempted to unlock the phone %d times. - The phone will now be reset to factory default. - - - - Try again in %d seconds. - - - Forgot pattern? - - - Account unlock - - Too many pattern attempts! - - To unlock, sign in with your Google account - - Username (email) - - Password - - Sign in - - Invalid username or password. - - Forgot your username or password\?\nVisit google.com/accounts/recovery - - - Checking... - - Unlock - - Sound on - - Sound off - - - Pattern started - - Pattern cleared - - Cell added - - Pattern completed - - - - \?123 - - ABC - - ALT - - - "%-l%P" - - - "%-l%p" - - - Factory test failed - - The FACTORY_TEST action - is only supported for packages installed in /system/app. - - No package was found that provides the - FACTORY_TEST action. - - Reboot - - - Mozilla/5.0 (Linux; U; Android %s) - AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 %sSafari/534.30 - - "Mobile " - - - The page at \'%s\' says: - - JavaScript - - Navigate away from this page?\n\n%s\n\nSelect OK to continue, or Cancel to stay on the current page. - - - Confirm - - - Tip: double-tap to zoom in and out. - - - AutoFill - - Setup AutoFill - - - \u0020 - - $1$2$3 - - - ,\u0020 - - $1$2$3 - - - attention|attn - - - province|region|other|provincia|bairro|suburb - - - company|business|organization|organisation|department|firma|firmenname|empresa|societe|société|ragione.?sociale|会社|название.?компании|单位|公司 - - - address.?line|address1|addr1|street|strasse|straße|hausnummer|housenumber|house.?name|direccion|dirección|adresse|indirizzo|住所1|morada|endereço|Адрес|地址 - - - address|adresse|indirizzo|住所|地址 - - - address.?line2|address2|addr2|street|suite|unit|adresszusatz|ergänzende.?angaben|direccion2|colonia|adicional|addresssuppl|complementnom|appartement|indirizzo2|住所2 - - - address.?line3|address3|addr3|street|line3|municipio|batiment|residence|indirizzo3 - - - country|location|国|国家 - - - zip|postal|post code|pcode|^1z$|postleitzahl|cp|cdp|cap|郵便番号|codigo|codpos|cep|Почтовый.?Индекс|邮政编码|邮编|郵遞區號 - - - zip|^-$|post2|codpos2 - - - city|town|ort|stadt|suburb|ciudad|provincia|localidad|poblacion|ville|commune|localita|市区町村|cidade|Город|市|分區 - - - state|county|region|province|land|county|principality|都道府県|estado|provincia|область|省|地區 - - - same as - - - use my - - - bill - - - ship - - - e.?mail|メールアドレス|Электронной.?Почты|邮件|邮箱|電郵地址 - - - user.?name|user.?id|vollständiger.?name|用户名 - - - ^name|full.?name|your.?name|customer.?name|firstandlastname|nombre.*y.*apellidos|^nom|お名前|氏名|^nome|姓名 - - - ^name|^nom|^nome - - - - irst.*name|initials|fname|first$|vorname|nombre|forename|prénom|prenom|名|nome|Имя - - - middle.*initial|m\\.i\\.|mi$ - - - middle.*name|mname|middle$|apellido.?materno|lastlastname - - - last.*name|lname|surname|last$|nachname|apellidos|famille|^nom|cognome|姓|morada|apelidos|surename|sobrenome|Фамилия - - - phone|telefonnummer|telefono|teléfono|telfixe|電話|telefone|telemovel|телефон|电话 - - - area.*code|acode|area - - - prefix|preselection|ddd - - - suffix - - - ext|ramal - - - card.?holder|name.?on.?card|ccname|owner|karteninhaber|nombre.*tarjeta|nom.*carte|nome.*cart|名前|Имя.*карты|信用卡开户名|开户名|持卡人姓名|持卡人姓名 - - - name - - - verification|card identification|cvn|security code|cvv code|cvc - - - number|card.?#|card.?no|ccnum|nummer|credito|numero|número|numéro|カード番号|Номер.*карты|信用卡号|信用卡号码|信用卡卡號 - - - expir|exp.*month|exp.*date|ccmonth|gueltig|gültig|monat|fecha|date.*exp|scadenza|有効期限|validade|Срок действия карты|月 - - - exp|^/|year|ablaufdatum|gueltig|gültig|yahr|fecha|scadenza|有効期限|validade|Срок действия карты|年|有效期 - - - ^card - - - fax|télécopie|telecopie|ファックス|факс|传真|傳真 - - - country.*code|ccode|_cc - - - ^\\($ - - - ^-$|^\\)$ - - - ^-$ - - - Province - - - Postal code - - - State - - - ZIP code - - - County - - - Island - - - District - - - Department - - - Prefecture - - - Parish - - - Area - - - Emirate - - - read Browser\'s history and bookmarks - - Allows the application to read all - the URLs that the Browser has visited, and all of the Browser\'s bookmarks. - - write Browser\'s history and bookmarks - - Allows an application to modify the - Browser\'s history or bookmarks stored on your tablet. Malicious applications - can use this to erase or modify your Browser\'s data. - - Allows an application to modify the - Browser\'s history or bookmarks stored on your phone. Malicious applications - can use this to erase or modify your Browser\'s data. - - - set alarm in alarm clock - - Allows the application to set an alarm in - an installed alarm clock application. Some alarm clock applications may - not implement this feature. - - - add voicemail - - Allows the application to add messages - to your voicemail inbox. - - - Modify Browser geolocation permissions - - Allows an application to modify the - Browser\'s geolocation permissions. Malicious applications - can use this to allow sending location information to arbitrary web sites. - - - verify packages - - Allows the application to verify a package is - installable. - - - bind to a package verifier - - Allows the holder to make requests of - package verifiers. Should never be needed for normal applications. - - - Do you want the browser to remember this password? - - Not now - - Remember - - Never - - - You do not have permission to open this page. - - - Text copied to clipboard. - - - More - - Menu+ - - space - - enter - - delete - - - - - Search - - Search - - Search query - - Clear query - - Submit query - - Voice search - - - 1 month ago - - Before 1 month ago - - - - 1 second ago - %d seconds ago - - - - - 1 minute ago - %d minutes ago - - - - - 1 hour ago - %d hours ago - - - - - Last %d days - - - - Last month - - - Older - - - - yesterday - %d days ago - - - - - in 1 second - in %d seconds - - - - - in 1 minute - in %d minutes - - - - - in 1 hour - in %d hours - - - - - tomorrow - in %d days - - - - - 1 sec ago - %d secs ago - - - - - 1 min ago - %d mins ago - - - - - 1 hour ago - %d hours ago - - - - - yesterday - %d days ago - - - - - in 1 sec - in %d secs - - - - - in 1 min - in %d mins - - - - - in 1 hour - in %d hours - - - - - tomorrow - in %d days - - - - on %s - - at %s - - in %s - - - day - - days - - hour - - hours - - min - - mins - - sec - - secs - - week - - weeks - - year - - years - - - - Cannot play video - - Sorry, this video is not valid for streaming to this device. - - Sorry, this video cannot be played. - - OK - - - - - - "%1$s, %2$s" - - - - "noon" - - "Noon" - - "midnight" - - "Midnight" - - - - - - - - - - - - - %1$02d:%2$02d - - - %1$d:%2$02d:%3$02d - - - Select all - - - Cut - - - Copy - - - Paste - - - Replace\u2026 - - - Delete - - - Copy URL - - - Select text... - - - Text selection - - - add to dictionary - - - delete - - - Input method - - - Text actions - - - Low on space - - Tablet storage space is getting low. - - Phone storage space is getting low. - - - OK - - Cancel - - OK - - Cancel - - Attention - - - Loading... - - - ON - - OFF - - - Complete action using - - Use by default for this action. - - Clear default in Home Settings > Applications > Manage applications. - - Select an action - - Select an application for the USB device - - No applications can perform this action. - - - - Unfortunately, %1$s has stopped. - - Unfortunately, the process %1$s has - stopped. - - - - %2$s is not responding.\n\nWould you like to close it? - - Activity %1$s is not responding.\n\nWould you like to close it? - - %1$s is not responding. Would you like to close it? - - Process %1$s is not responding.\n\nWould you like to close it? - - OK - - Report - - Wait - - Application redirected - - %1$s is now running. - - %1$s was originally launched. - - Scale - - Always show - - Re-enable this with Settings > Applications > Manage applications. - - - The application %1$s - (process %2$s) has violated its self-enforced StrictMode policy. - - The process %1$s has - has violated its self-enforced StrictMode policy. - - - Android is upgrading... - - - Optimizing application - %1$d of - %2$d. - - - Starting applications. - - - Finishing boot. - - - %1$s running - - - Select to switch to application - - - Switch applications? - - - Another application is already running - that must be stopped before you can start a new one. - - Return to %1$s - Don\'t start the new application. - - Start %1$s - Stop the old application without saving. - - - Select an action for text - - - Ringer volume - - Media volume - - Playing through Bluetooth - - Silent ringtone selected - - In-call volume - - Bluetooth in-call volume - - Alarm volume - - Notification volume - - Volume - - - Bluetooth volume - - Ringtone volume - - Call volume - - Media volume - - Notification volume - - - - Default ringtone - - Default ringtone (%1$s) - - Silent - - Ringtones - - Unknown ringtone - - - - Wi-Fi network available - Wi-Fi networks available - - - - Open Wi-Fi network available - Open Wi-Fi networks available - - - - Sign in to Wi-Fi network - - - %1$s - - - Couldn\'t connect to Wi-Fi - - \u0020has a poor internet connection. - - - AndroidAP - - - Wi-Fi Direct - Start Wi-Fi Direct operation. This will turn off Wi-Fi client/hotspot operation. - Couldn\'t start Wi-Fi Direct - Wi-Fi Direct connection setup request from %1$s. Click OK to accept. - Wi-Fi Direct connection setup request from %1$s. Enter pin to proceed. - WPS pin %1$s needs to be entered on the peer device %2$s for connection setup to proceed - Wi-Fi Direct is on - Touch for settings - - - Insert character - - - - Unknown application - - Sending SMS messages - - A large number of SMS messages are being sent. Select \"OK\" to continue, or \"Cancel\" to stop sending. - - OK - - Cancel - - - - SIM card removed - - The mobile network will be unavailable until you restart with a valid SIM card inserted. - - Done - - SIM card added - - You must restart your device to access the mobile network. - - Restart - - - - - Set time - - Set date - - Set - - - - Default - - %1$s, %2$s - - No permissions required - - Hide - - Show all - - - - USB Mass Storage - - - USB connected - - You have connected to your computer via USB. Touch the button below if you want to copy files between your computer and your Android\u2018s USB storage. - - You have connected to your computer via USB. Touch the button below if you want to copy files between your computer and your Android\u2018s SD card. - - Turn on USB storage - - There is a problem using your USB storage for USB mass storage. - - There is a problem using your SD card for USB mass storage. - - USB connected - - Select to copy files to/from your computer. - - - Turn off USB storage - - Select to turn off USB storage. - - - - - USB storage in use - - Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s USB storage from your computer. - - Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer. - - Turn off USB storage - - There was a problem turning off USB storage. Check to make sure you have unmounted the USB host, then try again. - - - Turn on USB storage - - If you turn on USB storage, some applications you are using will stop and may be unavailable until you turn off USB storage. - - USB operation unsuccessful - - OK - - - Connected as a media device - - Connected as a camera - - Connected as an installer - - Connected to a USB accessory - - Touch for other USB options - - - - - Format USB storage - - Format SD card - - Format USB storage, erasing all files stored there? Action cannot be reversed! - - Are you sure you want to format the SD card? All data on your card will be lost. - - Format - - - USB debugging connected - - Select to disable USB debugging. - - - - - - - "" - - - Select input method - - Configure input methods - - \u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ - \u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ - - candidates - - - - Preparing USB storage - - Preparing SD card - Checking for errors. - - - Blank USB storage - - Blank SD card - - USB storage blank or has unsupported filesystem. - SD card blank or has unsupported filesystem. - - - Damaged USB storage - - Damaged SD card - - USB storage damaged. You may have to reformat it. - SD card damaged. You may have to reformat it. - - - USB storage unexpectedly removed - - SD card unexpectedly removed - - Unmount USB storage before removing to avoid data loss. - Unmount SD card before removing to avoid data loss. - - - USB storage safe to remove - - SD card safe to remove - - You can safely remove USB storage. - You can safely remove SD card. - - - Removed USB storage - - Removed SD card - - USB storage removed. Insert new media. - SD card removed. Insert a new one. - - - No matching activities found - - - - update component usage statistics - - Allows the modification of collected component usage statistics. Not for use by normal applications. - - - - Allows to invoke default container service to copy content. Not for use by normal applications. - - Allows to invoke default container service to copy content. Not for use by normal applications. - - - Tap twice for zoom control - - - - Error inflating widget - - - Go - - - Search - - - Send - - - Next - - - Done - - - Prev - - - Execute - - - - - - - Dial number\nusing %s - - - Create contact\nusing %s - - - - - - - - The following one or more applications request permission to access your account, now and in the future. - Do you want to allow this request? - Access Request - Allow - Deny - Permission Requested - Permission Requested\nfor account %s - - - Input method - - Sync - - Accessibility - - Wallpaper - - Change wallpaper - - - /data/eri.xml - - - VPN is activated. - - VPN is activated by %s - - Tap to manage the network. - - Connected to %s. Tap to manage the network. - - - - Choose file - - No file chosen - - Reset - - Submit - - - - Car mode enabled - Select to exit car mode. - - - - Tethering or hotspot active - Touch to configure - - - Back - Next - - - Skip - - - - High mobile data use - Touch to learn more about mobile data use - - - - Mobile data limit exceeded - Touch to learn more about mobile data use - - - No matches - - - Find on page - - - - - 1 match - - %d of %d - - - - Done - - - - Unmounting USB storage... - - Unmounting SD card... - - Erasing USB storage... - - Erasing SD card... - - Couldn\'t erase USB storage. - - Couldn\'t erase SD card. - - SD card was removed before being unmounted. - - USB storage is currently being checked. - - SD card is currently being checked. - - SD card has been removed. - - USB storage is currently in use by a computer. - - SD card is currently in use by a computer. - - External media in unknown state. - - - - Share - - Find - - Web Search - - - Location request from %s - - Location request - - Requested by %1$s (%2$s) - - Yes - - No - - - Delete limit exceeded - - There are %1$d deleted items for %2$s, account %3$s. What would you like to do? - - Delete the items. - - Undo the deletes. - - Do nothing for now. - - - Select an account - - "Add an account" - "Which account would you like to use?" - - - Add account - - - - Increment - - Decrement - - %s tap and hold. - - Slide up to increment and down to decrement. - - - - Increment minute - - Decrement minute - - Increment hour - - Decrement hour - - Set PM - - Set AM - - - - Increment month - - Decrement month - - Increment day - - Decrement day - - Increment year - - Decrement year - - - - checked - - not checked - - - - selected - - not selected - - - - on - - off - - - - pressed - - not pressed - - - - Alt - - Cancel - - Delete - - Done - - Mode change - - Shift - - Enter - - - - Choose an application - - - - Share with - - Share with %s - - - - - "Sliding handle. Tap and hold." - - - Up for %s. - - Down for %s. - - "Left for %s. - - Right for %s. - - - Unlock - - Camera - - Silent - - Sound on - - - Swipe to unlock. - - - Plug in a headset to hear password keys spoken aloud. - - Dot. - - - Navigate home - - Navigate up - - More options - - - Internal Storage - - - SD Card - - - USB storage - - - Edit... - - - Data usage warning - - Touch to view usage and settings - - - 2G-3G data disabled - - 4G data disabled - - Mobile data disabled - - Wi-Fi data disabled - - Touch to enable - - - 2G-3G data limit exceeded - - 4G data limit exceeded - - Mobile data limit exceeded - - Wi-Fi data limit exceeded - - %s over specified limit - - - Background data restricted - - Touch to remove restriction - - - - Security certificate - - This certificate is valid. - - Issued to: - - Common name: - - Organization: - - Organizational unit: - - Issued by: - - Validity: - - Issued on: - - Expires on: - - Serial number: - - Fingerprints: - - SHA-256 fingerprint: - - SHA-1 fingerprint: - - - See all... - - Select activity - - - Share with... - - - - - Device locked. - - - ", " - - - Sending... - - - Launch Browser? - - - Accept Call? - - diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php deleted file mode 100644 index f225232f..00000000 --- a/wp-fdroid/wp-fdroid.php +++ /dev/null @@ -1,1017 +0,0 @@ -'; - if(isset($app[2]) && trim($app[2])) { - echo ''; - } - echo '

'; - echo $app[1].'
'; - if(isset($app[3]) && trim($app[3])) { - echo ''.$app[3].'

'; - } - echo ''; - } - fclose($handle); - } - echo $after_widget; - } - - function update($new_instance, $old_instance) { - $instance = array(); - $instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : ''; - return $instance; - } - - function form($instance) { - if (isset($instance['title'])) { - $title = $instance['title']; - } - else { - $title = __('New title', 'text_domain'); - } - ?> -

- - -

- inited=false; - $this->site_path=getenv('DOCUMENT_ROOT'); - add_action('widgets_init', function() { - register_widget('FDroidLatestWidget'); - }); - } - - - // Register additional query variables. (Handler for the 'query_vars' filter) - function queryvars($qvars) { - $qvars[]='fdfilter'; - $qvars[]='fdcategory'; - $qvars[]='fdid'; - $qvars[]='fdpage'; - $qvars[]='fdstyle'; - return $qvars; - } - - - // Lazy initialise. All non-trivial members should call this before doing anything else. - function lazyinit() { - if(!$this->inited) { - load_plugin_textdomain($this->textdom, PLUGINDIR.'/'.dirname(plugin_basename(__FILE__)), dirname(plugin_basename(__FILE__))); - - $this->inited=true; - } - } - - // Gets a required query parameter by name. - function getrequiredparam($name) { - global $wp_query; - if(!isset($wp_query->query_vars[$name])) - wp_die("Missing parameter ".$name,"Error"); - return $wp_query->query_vars[$name]; - } - - // Handler for the 'fdroidrepo' shortcode. - // $attribs - shortcode attributes - // $content - optional content enclosed between the starting and - // ending shortcode - // Returns the generated content. - function do_shortcode($attribs,$content=null) { - global $wp_query,$wp_rewrite; - $this->lazyinit(); - - // Init local query vars - foreach($this->queryvars(array()) as $qv) { - if(array_key_exists($qv,$wp_query->query_vars)) { - $query_vars[$qv] = $wp_query->query_vars[$qv]; - } else { - $query_vars[$qv] = null; - } - } - - // Sanity check and standardise all query variables... - if(!isset($query_vars['fdpage']) || !is_numeric($query_vars['fdpage']) || $query_vars['fdpage'] <= 0) { - $query_vars['fdpage'] = 1; - } else { - $query_vars['fdpage'] = strval(intval($query_vars['fdpage'])); - } - if(isset($query_vars['fdstyle']) && ($query_vars['fdstyle'] != 'list' && $query_vars['fdstyle'] != 'grid')) { - $query_vars['fdstyle'] = 'list'; - } - if(isset($query_vars['fdcategory'])) { - if($query_vars['fdcategory'] == 'All categories') { - unset($query_vars['fdcategory']); - } else { - $query_vars['fdcategory'] = sanitize_text_field($query_vars['fdcategory']); - } - } - if(isset($query_vars['fdfilter'])) { - $query_vars['fdfilter'] = sanitize_text_field($query_vars['fdfilter']); - } else { - if(isset($attribs['search'])) { - $query_vars['fdfilter'] = ''; - } - } - if(isset($query_vars['fdid'])) { - $query_vars['fdid'] = sanitize_text_field($query_vars['fdid']); - } - - $out = ''; - - if($query_vars['fdid']!==null) { - $out.=$this->get_app($query_vars); - } else { - $out.='
'; - $out.='

'; - $out.=''; - $out.='

'; - $out.=$this->makeformdata($query_vars); - $out.='
'."\n"; - - $out.=$this->get_apps($query_vars); - } - - return $out; - } - - - // Get a URL for a full description of a license, as given by one of our - // pre-defined license abbreviations. This is a temporary function, as this - // needs to be data-driven so the same information can be used by the client, - // the web site and the documentation. - function getlicenseurl($license) { - switch($license) { - case 'MIT': - return 'https://www.gnu.org/licenses/license-list.html#X11License'; - case 'NewBSD': - return 'https://www.gnu.org/licenses/license-list.html#ModifiedBSD'; - case 'FreeBSD': - return 'https://www.gnu.org/licenses/license-list.html#FreeBSD'; - case 'BSD': - return 'https://www.gnu.org/licenses/license-list.html#OriginalBSD'; - case 'GPLv3': - case 'GPLv3+': - return 'https://www.gnu.org/licenses/license-list.html#GNUGPLv3'; - case 'GPLv2': - case 'GPLv2+': - return 'https://www.gnu.org/licenses/license-list.html#GPLv2'; - case 'AGPLv3': - case 'AGPLv3+': - return 'https://www.gnu.org/licenses/license-list.html#AGPLv3.0'; - case 'LGPL': - return 'https://www.gnu.org/licenses/license-list.html#LGPL'; - case 'LGPLv3': - return 'https://www.gnu.org/licenses/license-list.html#LGPLv3'; - case 'LGPLv2.1': - return 'https://www.gnu.org/licenses/license-list.html#LGPLv2.1'; - case 'Apache2': - return 'https://www.gnu.org/licenses/license-list.html#apache2'; - case 'WTFPL': - return 'https://www.gnu.org/licenses/license-list.html#WTFPL'; - case 'ISC': - return 'https://www.gnu.org/licenses/license-list.html#ISC'; - case 'Expat': - return 'https://www.gnu.org/licenses/license-list.html#Expat'; - case 'Artistic2': - return 'https://www.gnu.org/licenses/license-list.html#ArtisticLicense2'; - case 'CC0': - return 'https://www.gnu.org/licenses/license-list.html#CC0'; - case 'PublicDomain': - return 'https://www.gnu.org/licenses/license-list.html#PublicDomain'; - case 'Unlicense': - return 'https://www.gnu.org/licenses/license-list.html#Unlicense'; - case 'MPL': - return 'https://www.gnu.org/licenses/license-list.html#MPL'; - case 'MPL2': - return 'https://www.gnu.org/licenses/license-list.html#MPL-2.0'; - case 'NCSA': - return 'https://www.gnu.org/licenses/license-list.html#NCSA'; - case 'Zlib': - return 'https://www.gnu.org/licenses/license-list.html#ZLib'; - case 'EPL': - return 'https://www.gnu.org/licenses/license-list.html#EPL'; - case 'EUPL': - return 'https://www.gnu.org/licenses/license-list.html#EUPL'; - default: - return null; - } - } - function androidversion($sdkLevel) { - switch ($sdkLevel) { - case 24: return "7.0"; - case 23: return "6.0"; - case 22: return "5.1"; - case 21: return "5.0"; - case 20: return "4.4W"; - case 19: return "4.4"; - case 18: return "4.3"; - case 17: return "4.2"; - case 16: return "4.1"; - case 15: return "4.0.3"; - case 14: return "4.0"; - case 13: return "3.2"; - case 12: return "3.1"; - case 11: return "3.0"; - case 10: return "2.3.3"; - case 9: return "2.3"; - case 8: return "2.2"; - case 7: return "2.1"; - case 6: return "2.0.1"; - case 5: return "2.0"; - case 4: return "1.6"; - case 3: return "1.5"; - case 2: return "1.1"; - case 1: return "1.0"; - default: return "?"; - } - } - - function get_app($query_vars) { - global $permissions_data; - $permissions_object = new AndroidPermissions($this->site_path.'/wp-content/plugins/wp-fdroid/AndroidManifest.xml', - $this->site_path.'/wp-content/plugins/wp-fdroid/strings.xml', - sys_get_temp_dir().'/android-permissions.cache'); - $permissions_data = $permissions_object->get_permissions_array(); - - // Get app data - $xml = simplexml_load_file($this->site_path.'/repo/index.xml'); - foreach($xml->children() as $app) { - - $attrs=$app->attributes(); - if($attrs['id']==$query_vars['fdid']) { - $apks=array();; - foreach($app->children() as $el) { - switch($el->getName()) { - case "name": - $name=$el; - break; - case "icon": - $icon=$el; - break; - case "summary": - $summary=$el; - break; - case "desc": - $desc=$el; - break; - case "license": - $license=$el; - break; - case "author": - $author=$el; - break; - case "email": - $email=$el; - break; - case "source": - $source=$el; - break; - case "tracker": - $issues=$el; - break; - case "changelog": - $changelog=$el; - break; - case "donate": - $donate=$el; - break; - case "flattr": - $flattr=$el; - break; - case "web": - $web=$el; - break; - case "antifeatures": - $antifeatures=$el; - break; - case "requirements": - $requirements=$el; - break; - case "package": - $thisapk=array(); - foreach($el->children() as $pel) { - switch($pel->getName()) { - case "version": - $thisapk['version']=$pel; - break; - case "vercode": - $thisapk['vercode']=$pel; - break; - case "added": - $thisapk['added']=$pel; - break; - case "apkname": - $thisapk['apkname']=$pel; - break; - case "srcname": - $thisapk['srcname']=$pel; - break; - case "hash": - $thisapk['hash']=$pel; - break; - case "size": - $thisapk['size']=$pel; - break; - case "sdkver": - $thisapk['sdkver']=$pel; - break; - case "maxsdkver": - $thisapk['maxsdkver']=$pel; - break; - case "nativecode": - $thisapk['nativecode']=$pel; - break; - case "permissions": - $thisapk['permissions']=$pel; - break; - } - } - $apks[]=$thisapk; - - } - } - - // Generate app diff data - foreach(array_reverse($apks, true) as $key=>$apk) { - if(isset($previous)) { - // Apk size - $apks[$key]['diff']['size'] = $apk['size']-$previous['size']; - } - - // Permissions - $permissions = explode(',',$apk['permissions']); - $permissionsPrevious = isset($previous['permissions'])?explode(',',$previous['permissions']):array(); - $apks[$key]['diff']['permissions']['added'] = array_diff($permissions, $permissionsPrevious); - $apks[$key]['diff']['permissions']['removed'] = array_diff($permissionsPrevious, $permissions); - - $previous = $apk; - } - - // Output app information - $out='
'; - $out.='
'; - $out.='

'.$name.""; - $out.="
".$summary."

"; - $out.="
"; - - $out.=str_replace('href="fdroid.app:', 'href="/repository/browse/?fdid=', $desc); - - if(isset($antifeatures)) { - $antifeaturesArray = explode(',',$antifeatures); - foreach($antifeaturesArray as $antifeature) { - $antifeatureDescription = $this->get_antifeature_description($antifeature); - $out.='

'.$antifeatureDescription['name'].'
'; - $out.=$antifeatureDescription['description'].' more...

'; - } - } - - $out.="

"; - $licenseurl=$this->getlicenseurl($license); - $out.="License: "; - if($licenseurl) - $out.=''; - $out.=$license; - if($licenseurl) - $out.=''; - - if(isset($requirements)) { - $out.='
Additional requirements: '.$requirements; - } - $out.="

"; - - $out.="

"; - if(strlen($web)>0) - $out.='Website: '.$web.'
'; - if(isset($author) && strlen($author)>0) - if(isset($email) && strlen($email)>0) - $out.='Author(s): '.$author.'
'; - else - $out.='Author(s): '.$author.'
'; - if(strlen($issues)>0) - $out.='Issue Tracker: '.$issues.'
'; - if(strlen($source)>0) - $out.='Source Code: '.$source.'
'; - if(strlen($changelog)>0) - $out.='Changelog: '.$changelog.'
'; - if(isset($donate) && strlen($donate)>0) - $out.='Donate: '.$donate.'
'; - if(isset($flattr) && strlen($flattr)>0) - $out.='Flattr:
'; - $out.="

"; - - $out.="

For full details and additional technical information, see "; - $out.="this application's page on the F-Droid wiki.

"; - - $out.=''; - - $out.="

Packages

"; - - $out.=''; - $out.="

Although APK downloads are available below to give "; - $out.="you the choice, you should be aware that by installing that way you "; - $out.="will not receive update notifications, and it's a less secure way "; - $out.="to download. "; - $out.="We recommend that you install the F-Droid client and use that.

"; - - $i=0; - foreach($apks as $apk) { - $first = $i+1==count($apks); - $out.="

Version ".$apk['version'].""; - $out.=" - Added on ".$apk['added']."
"; - - $hasminsdk = isset($apk['sdkver']); - $hasmaxsdk = isset($apk['maxsdkver']); - if($hasminsdk && $hasmaxsdk) { - $out.="

This version requires Android ".$this->androidversion($apk['sdkver'])." up to ".$this->androidversion($apk['maxsdkver'])."

"; - } elseif($hasminsdk) { - $out.="

This version requires Android ".$this->androidversion($apk['sdkver'])." or newer.

"; - } elseif($hasmaxsdk) { - $out.="

This version requires Android ".$this->androidversion($apk['maxsdkver'])." or old.

"; - } - - $hasabis = isset($apk['nativecode']); - if($hasabis) { - $abis = str_replace(',', ' ', $apk['nativecode']); - $out.="

This version uses native code and is built for: ".$abis."

"; - } - - // Is this source or binary? - $srcbuild = isset($apk['srcname']) && file_exists($this->site_path.'/repo/'.$apk['srcname']); - - $out.="

This version is built and signed by "; - if($srcbuild) { - $out.="F-Droid, and guaranteed to correspond to the source tarball below.

"; - } else { - $out.="the original developer.

"; - } - $out.='download apk '; - $out.=$this->human_readable_size($apk['size']); - $diffSize = $apk['diff']['size']; - if(abs($diffSize) > 500) { - $out.=' ('; - $out.=$diffSize>0?'+':''; - $out.=$this->human_readable_size($diffSize, 1).')'; - } - if(file_exists($this->site_path.'/repo/'.$apk['apkname'].'.asc')) { - $out.=' GPG Signature '; - } - if($srcbuild) { - $out.='
source tarball '; - $out.=$this->human_readable_size(filesize($this->site_path.'/repo/'.$apk['srcname'])); - if(file_exists($this->site_path.'/repo/'.$apk['srcname'].'.asc')) { - $out.=' GPG Signature '; - } - } - - if(isset($apk['permissions'])) { - // Permissions diff link - if($first == false) { - $permissionsAddedCount = count($apk['diff']['permissions']['added']); - $permissionsRemovedCount = count($apk['diff']['permissions']['removed']); - $divIdDiff='permissionsDiff'.$i; - if($permissionsAddedCount || $permissionsRemovedCount) { - $out.='
permissions diff'; - $out.=' ('; - if($permissionsAddedCount) - $out.='+'.$permissionsAddedCount; - if($permissionsAddedCount && $permissionsRemovedCount) - $out.='/'; - if($permissionsRemovedCount) - $out.='-'.$permissionsRemovedCount; - $out.=')'; - } - else - { - $out.='
no permission changes'; - } - } - - // Permissions list link - $permissionsListString = $this->get_permission_list_string(explode(',',$apk['permissions']), $permissions_data, $summary); - /*if($i==0) - $divStyleDisplay='block'; - else*/ - $divStyleDisplay='none'; - $divId='permissions'.$i; - $out.='
view permissions'; - $out.=' ['.$summary.']'; - $out.='
'; - - // Permissions list - $out.='
'; - $out.=$permissionsListString; - $out.='
'; - - // Permissions diff - { - $out.='
'; - $permissionsRemoved = $apk['diff']['permissions']['removed']; - usort($permissionsRemoved, "permissions_cmp"); - - // Added permissions - if($permissionsAddedCount) { - $out.='
ADDED

'; - $out.=$this->get_permission_list_string($apk['diff']['permissions']['added'], $permissions_data, $summary); - } - - // Removed permissions - if($permissionsRemovedCount) { - $out.='
REMOVED

'; - $out.=$this->get_permission_list_string($apk['diff']['permissions']['removed'], $permissions_data, $summary); - } - - $out.='
'; - } - } - else { - $out.='
no extra permissions needed
'; - } - - $out.='

'; - $i++; - } - - $out.='

Index

'; - - return $out; - } - } - return "

Application not found

"; - } - - private function get_permission_list_string($permissions, $permissions_data, &$summary) { - $out=''; - usort($permissions, "permissions_cmp"); - $permission_group_last = ''; - foreach($permissions as $permission) { - $permission_group = $permissions_data['permission'][$permission]['permissionGroup']; - if($permission_group != $permission_group_last) { - $permission_group_label = $permissions_data['permission-group'][$permission_group]['label']; - if($permission_group_label=='') $permission_group_label = 'Extra/Custom'; - $out.=''.strtoupper($permission_group_label).'
'; - $permission_group_last = $permission_group; - } - - $out.=$this->get_permission_protection_level_icon($permissions_data['permission'][$permission]['protectionLevel']).' '; - $out.=''.$permissions_data['permission'][$permission]['label'].' ['.$permission.']
'; - if($permissions_data['permission'][$permission]['description']) $out.=$permissions_data['permission'][$permission]['description'].'
'; - //$out.=$permissions_data['permission'][$permission]['comment'].'
'; - $out.='
'; - - if(!isset($summaryCount[$permissions_data['permission'][$permission]['protectionLevel']])) - $summaryCount[$permissions_data['permission'][$permission]['protectionLevel']] = 0; - $summaryCount[$permissions_data['permission'][$permission]['protectionLevel']]++; - } - - $summary = ''; - if(isset($summaryCount)) { - foreach($summaryCount as $protectionLevel => $count) { - $summary .= $this->get_permission_protection_level_icon($protectionLevel, 'regular').' '.$count; - $summary .= ', '; - } - } - $summary = substr($summary,0,-2); - - return $out; - } - - private function get_permission_protection_level_icon($protection_level, $size='adjusted') { - $iconString = ''; - if($protection_level=='dangerous') { - $iconString .= ''; // WARNING SIGN - } - elseif($protection_level=='normal') { - $iconString .= ''; // CIRCLED LATIN SMALL LETTER I - } - elseif($protection_level=='signature') { - $iconString .= ''; // HEAVY TEARDROP-SPOKED ASTERISK - } - elseif($protection_level=='signatureOrSystem') { - $iconString .= ''; // ATOM SYMBOL - } - else { - $iconString .= ''; // GEAR - } - - return $iconString; - } - - private function human_readable_size($size, $minDiv=0) { - $si_prefix = array('bytes','kB','MB'); - $div = 1024; - - for($i=0;(abs($size) > $div && $i < count($si_prefix)) || $i<$minDiv;$i++) { - $size /= $div; - } - - return round($size,max(0,$i-1)).' '.$si_prefix[$i]; - } - - private function get_antifeature_description($antifeature) { - // Anti feature names and descriptions - $antifeatureDescription['Ads']['name'] = 'Advertising'; - $antifeatureDescription['Ads']['description'] = 'This application contains advertising.'; - $antifeatureDescription['Tracking']['name'] = 'Tracks You'; - $antifeatureDescription['Tracking']['description'] = 'This application tracks and reports your activity to somewhere.'; - $antifeatureDescription['NonFreeNet']['name'] = 'Non-Free Network Services'; - $antifeatureDescription['NonFreeNet']['description'] = 'This application promotes a non-Free network service.'; - $antifeatureDescription['NonFreeAdd']['name'] = 'Non-Free Addons'; - $antifeatureDescription['NonFreeAdd']['description'] = 'This application promotes non-Free add-ons.'; - $antifeatureDescription['NonFreeDep']['name'] = 'Non-Free Dependencies'; - $antifeatureDescription['NonFreeDep']['description'] = 'This application depends on another non-Free application.'; - $antifeatureDescription['UpstreamNonFree']['name'] = 'Upstream Non-Free'; - $antifeatureDescription['UpstreamNonFree']['description'] = 'The upstream source code is non-free.'; - $antifeatureDescription['NonFreeAssets']['name'] = 'Non-Free Assets'; - $antifeatureDescription['NonFreeAssets']['description'] = 'This application contains non-free assets.'; - $antifeatureDescription['KnownVuln']['name'] = 'Known Vulnerability'; - $antifeatureDescription['KnownVuln']['description'] = 'This application known security vulnerabilities.'; - - if(isset($antifeatureDescription[$antifeature])) { - return $antifeatureDescription[$antifeature]; - } - return array('name'=>$antifeature); - } - - - function get_apps($query_vars) { - - $xml = simplexml_load_file($this->site_path."/repo/index.xml"); - $matches = $this->show_apps($xml,$query_vars,$numpages); - - $out=''; - - if(($query_vars['fdfilter']===null || $query_vars['fdfilter']!='') && $numpages>0) - { - $out.='
'; - if($query_vars['fdfilter']===null) { - - $categories = array('All categories'); - $handle = fopen(getenv('DOCUMENT_ROOT').'/repo/categories.txt', 'r'); - if ($handle) { - while (($buffer = fgets($handle, 4096)) !== false) { - $categories[] = rtrim($buffer); - } - fclose($handle); - } - - $out.='
'; - $out.=$this->makeformdata($query_vars); - - $out.=''; - - $out.='
'."\n"; - } - else { - $out.='Applications matching "'.esc_attr($query_vars['fdfilter']).'"'; - } - $out.="
"; - - $out.='
'; - $out.='List | '; - $out.='Grid'; - $out.='
'; - - $out.='
'; - } - - if($numpages>0) { - $out.=$matches; - - $out.='

'; - - $out.='

'; - $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; - $out.='
'; - - $out.='
'; - if($numpages>1) { - for($i=1;$i<=$numpages;$i++) { - if($i == $query_vars['fdpage']) { - $out.=''.$i.''; - } else { - $out.=''; - $out.=$i; - $out.=''; - } - $out.=' '; - } - $out.=' '; - } - $out.='
'; - - $out.='
'; - if($query_vars['fdpage']!=$numpages) { - $out.='next> '; - } - $out.='
'; - - $out.='

'; - } else if($query_vars['fdfilter']!='') { - $out.='

No matches

'; - } - - return $out; - } - - - function makeformdata($query_vars) { - - $out=''; - - $out.=''; - foreach($query_vars as $name => $value) { - if($value !== null && $name != 'fdfilter' && $name != 'fdpage') - $out.=''; - } - - return $out; - } - - - function show_apps($xml,$query_vars,&$numpages) { - - $skipped=0; - $got=0; - $total=0; - - if($query_vars['fdstyle']=='grid') { - $outputter = new FDOutGrid(); - } else { - $outputter = new FDOutList(); - } - - $out = ""; - - $out.=$outputter->outputStart(); - - foreach($xml->children() as $app) { - - if($app->getName() == 'repo') continue; - $appinfo['attrs']=$app->attributes(); - $appinfo['id']=$appinfo['attrs']['id']; - foreach($app->children() as $el) { - switch($el->getName()) { - case "name": - $appinfo['name']=$el; - break; - case "icon": - $appinfo['icon']=$el; - break; - case "summary": - $appinfo['summary']=$el; - break; - case "desc": - $appinfo['description']=$el; - break; - case "license": - $appinfo['license']=$el; - break; - case "category": - $appinfo['category']=$el; - break; - } - } - - if(($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['id'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']) || stristr($appinfo['description'],$query_vars['fdfilter']))) && (!isset($query_vars['fdcategory']) || $query_vars['fdcategory'] && $query_vars['fdcategory']==$appinfo['category'])) { - if($skipped<($query_vars['fdpage']-1)*$outputter->perpage) { - $skipped++; - } else if($got<$outputter->perpage) { - $out.=$outputter->outputEntry($query_vars, $appinfo); - $got++; - } - $total++; - } - - } - - $out.=$outputter->outputEnd(); - - $numpages = ceil((float)$total/$outputter->perpage); - - return $out; - } -} - -// Class to output app entries in a detailed list format -class FDOutList -{ - var $perpage=30; - - function FDOutList() { - } - - function outputStart() { - return ''; - } - - function outputEntry($query_vars, $appinfo) { - $out=""; - $out.='
'."\n"; - $out.=''; - $out.='
'; - - $out.='
'; - - $out.='
'; - $out.='

Details...

'; - $out.="
\n"; - - $out.='

'.$appinfo['name'].""; - $out.="
".$appinfo['summary']."

\n"; - - $out.="
\n"; - $out.='
'; - - return $out; - } - - function outputEnd() { - return ''; - } -} - -// Class to output app entries in a compact grid format -class FDOutGrid -{ - var $perpage=80; - - var $itemCount = 0; - - function FDOutGrid() { - } - - function outputStart() { - return "\n".''."\n"; - } - - function outputEntry($query_vars, $appinfo) { - $link=makelink($query_vars, array('fdid'=>$appinfo['id'])); - - $out=''; - - if($this->itemCount%4 == 0 && $this->itemCount > 0) - { - $out.=''."\n"; - } - - $out.='\n"; - - $this->itemCount++; - return $out; - } - - function outputEnd() { - return '
'; - $out.='

'; - $out.='

"; - $out.='

'; - $out.="
'."\n"; - } -} - -function permissions_cmp($a, $b) { - global $permissions_data; - - $aProtectionLevel = $permissions_data['permission'][$a]['protectionLevel']; - $bProtectionLevel = $permissions_data['permission'][$b]['protectionLevel']; - - if($aProtectionLevel != $bProtectionLevel) { - if(strlen($aProtectionLevel)==0) return 1; - if(strlen($bProtectionLevel)==0) return -1; - - return strcmp($aProtectionLevel, $bProtectionLevel); - } - - $aGroup = $permissions_data['permission'][$a]['permissionGroup']; - $bGroup = $permissions_data['permission'][$b]['permissionGroup']; - - if($aGroup != $bGroup) { - return strcmp($aGroup, $bGroup); - } - - return strcmp($a, $b); -} - -// Make a link to this page, with the current query vars attached and desired params added/modified -function makelink($query_vars, $params=array()) { - $link=get_permalink(); - - $p = array_merge($query_vars, $params); - - // Page 1 is the default, don't clutter urls with it... - if($p['fdpage'] == 1) - unset($p['fdpage']); - // Likewise for list style... - if($p['fdstyle'] == 'list') - unset($p['fdstyle']); - - $vars=linkify($p); - if(strlen($vars)==0) - return $link; - if(strpos($link,'?')===false) - $link.='?'; - else - $link.='&'; - return $link.$vars; -} - -// Return the key value pairs in http-get-parameter format as a string -function linkify($vars) { - $retvar = ''; - foreach($vars as $k => $v) { - if($k!==null && $v!==null && $v!='') - $retvar .= $k.'='.urlencode($v).'&'; - } - return substr($retvar,0,-1); -} - -$wp_fdroid = new FDroid(); - - -?> From f43da8cd144f6e51a87c9e0a0d09c68210348316 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 09:56:28 +0200 Subject: [PATCH 10/14] add new files to MANIFEST.in They need to be there in order to be included in the source tarball. --- MANIFEST.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index a5945d70..f5177d29 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,6 +5,7 @@ include fdroid include jenkins-build include makebuildserver include buildserver/config.buildserver.py +include buildserver/gradle include buildserver/provision-android-ndk include buildserver/provision-android-sdk include buildserver/provision-apt-get-install @@ -13,12 +14,15 @@ include buildserver/provision-gradle include buildserver/provision-pip include buildserver/provision-qt-sdk include buildserver/provision-ubuntu-trusty-paramiko +include buildserver/setup-env-vars include buildserver/Vagrantfile include completion/bash-completion include examples/config.py include examples/fdroid-icon.png include examples/makebuildserver.config.py include examples/opensc-fdroid.cfg +include examples/public-read-only-s3-bucket-policy.json +include examples/template.yml include tests/getsig/run.sh include tests/getsig/make.sh include tests/getsig/getsig.java From 0a953814e21257d4d362af0468d67d749b069b05 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 10:59:05 +0200 Subject: [PATCH 11/14] update: always include name/summary/desc in index.xml if available With the new localization support, the name/summary/description in the metadata file becomes the global override. So most apps are not going to have those fields present in their metadata file. This fixes the index.xml generation to fall back to the localized versions of those fields when they are not set in the metadata field. https://forum.f-droid.org/t/what-has-happend-to-osmand --- fdroidserver/index.py | 43 ++++++++++++++++--- .../metadata/info.guardianproject.checkey.txt | 10 ----- .../en-US/description.txt | 1 + .../en-US/summary.txt | 1 + 4 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 tests/metadata/info.guardianproject.checkey/en-US/description.txt create mode 100644 tests/metadata/info.guardianproject.checkey/en-US/summary.txt diff --git a/fdroidserver/index.py b/fdroidserver/index.py index b0de4325..53d2787a 100644 --- a/fdroidserver/index.py +++ b/fdroidserver/index.py @@ -258,6 +258,35 @@ def make_v0(apps, apks, repodir, repodict, requestsdict): el.appendChild(doc.createCDATASection(value)) parent.appendChild(el) + def addElementCheckLocalized(name, app, key, doc, parent, default=''): + '''Fill in field from metadata or localized block + + For name/summary/description, they can come only from the app source, + or from a dir in fdroiddata. They can be entirely missing from the + metadata file if there is localized versions. This will fetch those + from the localized version if its not available in the metadata file. + ''' + + el = doc.createElement(name) + value = app.get(key) + lkey = key[:1].lower() + key[1:] + localized = app.get('localized') + if not value and localized: + for lang in ['en-US'] + [x for x in localized.keys()]: + if not lang.startswith('en'): + continue + if lang in localized: + value = localized[lang].get(lkey) + if value: + break + if not value and localized and len(localized) > 1: + lang = list(localized.keys())[0] + value = localized[lang].get(lkey) + if not value: + value = default + el.appendChild(doc.createTextNode(value)) + parent.appendChild(el) + root = doc.createElement("fdroid") doc.appendChild(root) @@ -312,16 +341,16 @@ def make_v0(apps, apks, repodir, repodict, requestsdict): addElement('added', app.added.strftime('%Y-%m-%d'), doc, apel) if app.lastUpdated: addElement('lastupdated', app.lastUpdated.strftime('%Y-%m-%d'), doc, apel) - addElement('name', app.Name, doc, apel) - addElement('summary', app.Summary, doc, apel) + + addElementCheckLocalized('name', app, 'Name', doc, apel) + addElementCheckLocalized('summary', app, 'Summary', doc, apel) + if app.icon: addElement('icon', app.icon, doc, apel) - if app.get('Description'): - description = app.Description - else: - description = '

No description available

' - addElement('desc', description, doc, apel) + addElementCheckLocalized('desc', app, 'Description', doc, apel, + '

No description available

') + addElement('license', app.License, doc, apel) if app.Categories: addElement('categories', ','.join(app.Categories), doc, apel) diff --git a/tests/metadata/info.guardianproject.checkey.txt b/tests/metadata/info.guardianproject.checkey.txt index eea6c7be..4beeec89 100644 --- a/tests/metadata/info.guardianproject.checkey.txt +++ b/tests/metadata/info.guardianproject.checkey.txt @@ -6,16 +6,6 @@ Issue Tracker:https://dev.guardianproject.info/projects/checkey/issues Bitcoin:1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk Auto Name:Checkey -Summary:Info on local apps -Description: -Checkey is a utility for getting information about the APKs that are installed -on your device. Starting with a list of all of the apps that you have -installed on your device, it will show you the APK signature with a single -touch, and provides links to virustotal.com and androidobservatory.org to -easily access the profiles of that APK. It will also let you export the -signing certificate and generate ApkSignaturePin pin files for use with the -TrustedIntents library. -. Current Version Code:9999999 diff --git a/tests/metadata/info.guardianproject.checkey/en-US/description.txt b/tests/metadata/info.guardianproject.checkey/en-US/description.txt new file mode 100644 index 00000000..568b9491 --- /dev/null +++ b/tests/metadata/info.guardianproject.checkey/en-US/description.txt @@ -0,0 +1 @@ +Checkey is a utility for getting information about the APKs that are installed on your device. Starting with a list of all of the apps that you have installed on your device, it will show you the APK signature with a single touch, and provides links to virustotal.com and androidobservatory.org to easily access the profiles of that APK. It will also let you export the signing certificate and generate ApkSignaturePin pin files for use with the TrustedIntents library. diff --git a/tests/metadata/info.guardianproject.checkey/en-US/summary.txt b/tests/metadata/info.guardianproject.checkey/en-US/summary.txt new file mode 100644 index 00000000..a4642ad1 --- /dev/null +++ b/tests/metadata/info.guardianproject.checkey/en-US/summary.txt @@ -0,0 +1 @@ +Info on local apps From 619c66e1dc595df29b5cb73a5b2e4d66ed56d7cd Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 15:56:50 +0200 Subject: [PATCH 12/14] gitlab-ci: filter new build fields in metadata_v0 test --- .gitlab-ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eb7704fd..7e17d7c8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,8 +7,8 @@ test: - ./complete-ci-tests # Test that the parsing of the .txt format didn't change. The metadata -# field 'Author Web Site' was added after 0.7.0, so that can't be part -# of the test. +# fields 'Author Web Site', 'antifeatures=', 'buildozer=', and 'sudo=' +# where added after 0.7.0, so that can't be part of the test. metadata_v0: script: - cd tests @@ -19,6 +19,10 @@ metadata_v0: - sed -i "s/'Author Email',/'Author Email',\n'Author Web Site',/" fdroidserver/metadata.py - git clone --depth 1 https://gitlab.com/fdroid/fdroiddata - cd fdroiddata + - sed -i -e '/antifeatures=/d' + -e '/buildozer=/d' + -e '/sudo=/d' + metadata/*.txt - ../tests/dump.py - cd .. - git reset --hard From be523a3f1aebdbb16ebc4364d8b9a47f7175b72d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 23:58:07 +0200 Subject: [PATCH 13/14] include all test files in source tarball --- MANIFEST.in | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index f5177d29..33226525 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -23,10 +23,133 @@ include examples/makebuildserver.config.py include examples/opensc-fdroid.cfg include examples/public-read-only-s3-bucket-policy.json include examples/template.yml -include tests/getsig/run.sh -include tests/getsig/make.sh +include tests/androguard_test.py +include tests/build.TestCase +include tests/common.TestCase +include tests/complete-ci-tests +include tests/config.py +include tests/description-parsing.py +include tests/dump_internal_metadata_format.py +include tests/extra/convert_metadata_to_yaml_then_txt.sh +include tests/extra/manual-vmtools-test.py include tests/getsig/getsig.java +include tests/getsig/make.sh +include tests/getsig/run.sh +include tests/gnupghome/pubring.gpg +include tests/gnupghome/random_seed +include tests/gnupghome/secring.gpg +include tests/gnupghome/trustdb.gpg +include tests/import_proxy.py +include tests/import.TestCase +include tests/index.TestCase +include tests/install.TestCase +include tests/keystore.jks +include tests/lint.TestCase +include tests/metadata/apk/info.guardianproject.urzip.yaml +include tests/metadata/apk/org.dyndns.fules.ck.yaml +include tests/metadata/app.with.special.build.params.txt +include tests/metadata/com.politedroid.txt +include tests/metadata/dump/com.politedroid.yaml +include tests/metadata/dump/org.adaway.yaml +include tests/metadata/dump/org.smssecure.smssecure.yaml +include tests/metadata/dump/org.videolan.vlc.yaml +include tests/metadata/fake.ota.update.txt +include tests/metadata/info.guardianproject.checkey/en-US/description.txt +include tests/metadata/info.guardianproject.checkey/en-US/phoneScreenshots/checkey-phone.png +include tests/metadata/info.guardianproject.checkey/en-US/phoneScreenshots/checkey.png +include tests/metadata/info.guardianproject.checkey/en-US/summary.txt +include tests/metadata/info.guardianproject.checkey.txt +include tests/metadata/info.guardianproject.urzip/en-US/changelogs/100.txt +include tests/metadata/info.guardianproject.urzip/en-US/full_description.txt +include tests/metadata/info.guardianproject.urzip/en-US/images/featureGraphic.png +include tests/metadata/info.guardianproject.urzip/en-US/images/icon.png +include tests/metadata/info.guardianproject.urzip/en-US/short_description.txt +include tests/metadata/info.guardianproject.urzip/en-US/title.txt +include tests/metadata/info.guardianproject.urzip/en-US/video.txt +include tests/metadata/info.guardianproject.urzip.yml +include tests/metadata/obb.main.oldversion.txt +include tests/metadata/obb.mainpatch.current.txt +include tests/metadata/obb.main.twoversions.txt +include tests/metadata/org.adaway.json +include tests/metadata/org.fdroid.ci.test.app.txt +include tests/metadata/org.fdroid.fdroid.txt +include tests/metadata/org.smssecure.smssecure.txt +include tests/metadata/org.videolan.vlc.yml +include tests/metadata/raw.template.txt +include tests/metadata-rewrite-yml/app.with.special.build.params.yml +include tests/metadata-rewrite-yml/fake.ota.update.yml +include tests/metadata-rewrite-yml/org.fdroid.fdroid.yml +include tests/metadata.TestCase +include tests/openssl-version-check-test.py +include tests/org.bitbucket.tickytacky.mirrormirror_1.apk +include tests/org.bitbucket.tickytacky.mirrormirror_2.apk +include tests/org.bitbucket.tickytacky.mirrormirror_3.apk +include tests/org.bitbucket.tickytacky.mirrormirror_4.apk +include tests/org.dyndns.fules.ck_20.apk +include tests/repo/categories.txt +include tests/repo/com.politedroid_3.apk +include tests/repo/com.politedroid_4.apk +include tests/repo/com.politedroid_5.apk +include tests/repo/com.politedroid_6.apk +include tests/repo/fake.ota.update_1234.zip +include tests/repo/index.xml +include tests/repo/main.1101613.obb.main.twoversions.obb +include tests/repo/main.1101615.obb.main.twoversions.obb +include tests/repo/main.1434483388.obb.main.oldversion.obb +include tests/repo/main.1619.obb.mainpatch.current.obb +include tests/repo/obb.main.oldversion_1444412523.apk +include tests/repo/obb.mainpatch.current_1619_another-release-key.apk +include tests/repo/obb.mainpatch.current_1619.apk +include tests/repo/obb.mainpatch.current/en-US/featureGraphic.png +include tests/repo/obb.mainpatch.current/en-US/icon.png +include tests/repo/obb.mainpatch.current/en-US/phoneScreenshots/screenshot-main.png +include tests/repo/obb.mainpatch.current/en-US/sevenInchScreenshots/screenshot-tablet-main.png +include tests/repo/obb.main.twoversions_1101613.apk +include tests/repo/obb.main.twoversions_1101615.apk +include tests/repo/obb.main.twoversions_1101617.apk +include tests/repo/obb.main.twoversions_1101617_src.tar.gz +include tests/repo/org.videolan.vlc/en-US/icon.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot10.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot12.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot15.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot18.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot20.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot22.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot4.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot7.png +include tests/repo/org.videolan.vlc/en-US/phoneScreenshots/screenshot9.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot0.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot11.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot13.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot14.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot16.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot17.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot19.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot1.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot21.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot23.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot2.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot3.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot5.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot6.png +include tests/repo/org.videolan.vlc/en-US/sevenInchScreenshots/screenshot8.png +include tests/repo/patch.1619.obb.mainpatch.current.obb +include tests/repo/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk include tests/run-tests +include tests/signindex/guardianproject.jar +include tests/signindex/guardianproject-v1.jar +include tests/signindex/testy.jar +include tests/signindex/unsigned.jar +include tests/source-files/fdroid/fdroidclient/AndroidManifest.xml +include tests/source-files/fdroid/fdroidclient/build.gradle +include tests/source-files/open-keychain/open-keychain/build.gradle +include tests/source-files/open-keychain/open-keychain/OpenKeychain/build.gradle +include tests/source-files/osmandapp/osmand/build.gradle +include tests/source-files/Zillode/syncthing-silk/build.gradle +include tests/stats/known_apks.txt include tests/update.TestCase include tests/urzip.apk +include tests/urzip-badcert.apk include tests/urzip-badsig.apk +include tests/urzip-release.apk +include tests/urzip-release-unsigned.apk From c1e9379f6708606474c1ce90be9099ccb00032ec Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 19 Jul 2017 23:59:47 +0200 Subject: [PATCH 14/14] remove errant trailing slash added in 7613c18dd80969cec9db0e209611c9ebc3176fed --- fdroidserver/verify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdroidserver/verify.py b/fdroidserver/verify.py index 85d1d2b2..bd629f97 100644 --- a/fdroidserver/verify.py +++ b/fdroidserver/verify.py @@ -81,7 +81,7 @@ def main(): net.download_file(url, dldir=tmp_dir) except requests.exceptions.HTTPError as e: try: - net.download_file(url.replace('/repo', '/archive/'), dldir=tmp_dir) + net.download_file(url.replace('/repo', '/archive'), dldir=tmp_dir) except requests.exceptions.HTTPError as e: raise FDroidException('Downloading %s failed. %s', (url, e))