From 52a8fde86cc7213178d8551d43a419254cea05dc Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Sun, 11 Dec 2011 15:34:21 +0100 Subject: [PATCH 01/20] Added grid view when listing apps in browse repository. Also, the WP plugin will now pass on all of the relevant query arguments via generated links by default. --- wp-fdroid/wp-fdroid.php | 309 +++++++++++++++++++++++++++------------- 1 file changed, 211 insertions(+), 98 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 8a79ad6d..2cd8b98a 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -16,9 +16,10 @@ class FDroid { // Our text domain, for internationalisation - var $textdom='wp-fdroid'; + private $textdom='wp-fdroid'; - var $site_path = "/home/fdroid/public_html"; + // TODO: Fix site path... + private $site_path = "/home/hansemil/MyDocuments/f-droid"; // Constructor function FDroid() { @@ -34,6 +35,7 @@ class FDroid $qvars[]='fdfilter'; $qvars[]='fdid'; $qvars[]='fdpage'; + $qvars[]='fdstyle'; return $qvars; } @@ -55,19 +57,6 @@ class FDroid return $wp_query->query_vars[$name]; } - // Make a link to this page, with the given query parameter string added - function makelink($params) { - $link=get_permalink(); - if(strlen($params)==0) - return $link; - if(strpos($link,'?')===false) - $link.='?'; - else - $link.='&'; - $link.=$params; - return $link; - } - // Handler for the 'fdroidrepo' shortcode. // $attribs - shortcode attributes // $content - optional content enclosed between the starting and @@ -77,32 +66,37 @@ class FDroid global $wp_query,$wp_rewrite; $this->lazyinit(); - $page=1; - if(isset($wp_query->query_vars['fdpage'])) { - $page=(int)$wp_query->query_vars['fdpage']; - if($page==0) - $page=1; - } + + // 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; + } + } + + // Santiy check query vars + if(!isset($query_vars['fdpage']) || !is_numeric($query_vars['fdpage']) || $query_vars['fdpage'] <= 0) { + $query_vars['fdpage'] = 1; + } - $filter=$wp_query->query_vars['fdfilter']; - $fdid=$wp_query->query_vars['fdid']; - - if($fdid!==null) - $out=$this->get_app($fdid); + if($query_vars['fdid']!==null) + $out=$this->get_app($query_vars); else - $out=$this->get_apps($page,$filter); + $out=$this->get_apps($query_vars); return $out; } - function get_app($id) { + function get_app($query_vars) { $xml = simplexml_load_file($this->site_path."/repo/index.xml"); foreach($xml->children() as $app) { $attrs=$app->attributes(); - if($attrs['id']==$id) { + if($attrs['id']==$query_vars['fdid']) { $apks=array();; foreach($app->children() as $el) { switch($el->getName()) { @@ -199,7 +193,7 @@ class FDroid $out.="

"; } - $out.='

Index

'; + $out.='

Index

'; return $out; } @@ -208,88 +202,42 @@ class FDroid } - function get_apps($page,$filter=null) { + function get_apps($query_vars) { - if($filter===null) - $out="

All applications"; + $out=''; + + $out.='

'; + if($query_vars['fdfilter']===null) + $out.="All applications"; else - $out="

Applications matching ".$filter; - $out.="

"; + $out.="Applications matching ".$query_vars['fdfilter']; + $out.="
"; - $perpage=30; - $skipped=0; - $got=0; - $total=0; + $out.='
'; + $out.='List | '; + $out.='Grid'; + $out.='
'; + + $out.='
'; $xml = simplexml_load_file($this->site_path."/repo/index.xml"); - foreach($xml->children() as $app) { - - if($app->getName() == 'repo') continue; - $attrs=$app->attributes(); - $id=$attrs['id']; - foreach($app->children() as $el) { - switch($el->getName()) { - case "name": - $name=$el; - break; - case "icon": - $icon=$el; - break; - case "summary": - $summary=$el; - break; - case "license": - $license=$el; - break; - } - } - - if($filter===null || stristr($name,$filter)) { - if($skipped<($page-1)*$perpage) { - $skipped++; - } else if($got<$perpage) { - - $out.="
\n"; - $out.='
'; - - $out.='
'; - - $out.='
'; - $out.='

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

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

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

\n"; - - $out.="
\n"; - - $got++; - } - $total++; - } - - } - - $numpages=ceil((float)$total/$perpage); + $out.=$this->show_apps($xml,$query_vars,$numpages); $out.='

'; - if($page==1) { + if($query_vars['fdpage']==1) { $out.="<<first "; $out.="<prev "; } else { - $out.='<<first '; - $out.='<<prev '; + $out.='<<first '; + $out.='<<prev '; } - $out.=" Page $page of $numpages "; - if($page==$numpages) { + $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; + if($query_vars['fdpage']==$numpages) { $out.="next> "; $out.="last>> "; } else { - $out.='next> '; - $out.='last>> '; + $out.='next> '; + $out.='last>> '; } $out.='

'; @@ -297,9 +245,174 @@ class FDroid } + 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 "license": + $appinfo['license']=$el; + break; + } + } + + if($query_vars['fdfilter']===null || stristr($appinfo['name'],$query_vars['fdfilter'])) { + 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.='

Details...'; + $out.="

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

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

\n"; + + $out.="
\n"; + + 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"; + } +} + +// 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(); + $vars=linkify(array_merge($query_vars, $params)); + 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.'='.$v.'&'; + } + return substr($retvar,0,-1); +} + + $wp_fdroid = new FDroid(); From e05c401f1226603b85d2d2877b2ff8babcdec2f2 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Mon, 12 Dec 2011 21:21:07 +0100 Subject: [PATCH 02/20] Get site path (www-root) from environment variable. (Won't work on IIS...) --- wp-fdroid/wp-fdroid.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 2cd8b98a..fe05c092 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -18,8 +18,7 @@ class FDroid // Our text domain, for internationalisation private $textdom='wp-fdroid'; - // TODO: Fix site path... - private $site_path = "/home/hansemil/MyDocuments/f-droid"; + private $site_path; // Constructor function FDroid() { @@ -27,6 +26,7 @@ class FDroid add_shortcode('fdroidrepo',array($this, 'do_shortcode')); add_filter('query_vars',array($this, 'queryvars')); $this->inited=false; + $this->site_path=getenv('DOCUMENT_ROOT'); } From 8f50665e8c2a8f8e9016dd1e6f7b35f976bf1df2 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Sun, 18 Dec 2011 21:16:20 +0100 Subject: [PATCH 03/20] Implemented searching for apps in the repository. Adds a new shortcode attribute "search" for the shortcode "fdroidrepo". When this is set, a search field will be shown above the app listing. Uses the fdfilter search code to do the search result filtering. --- wp-fdroid/wp-fdroid.php | 113 ++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 38 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index fe05c092..7d1b1dfc 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -81,10 +81,20 @@ class FDroid $query_vars['fdpage'] = 1; } - if($query_vars['fdid']!==null) - $out=$this->get_app($query_vars); - else - $out=$this->get_apps($query_vars); + $out = ''; + + if(isset($attribs['search']) && $query_vars['fdfilter']===null) { + $query_vars['fdfilter'] = ''; + } + + if($query_vars['fdid']!==null) { + $out.=$this->get_app($query_vars); + } else { + if($query_vars['fdfilter'] !== null) + $out.=$this->show_search($query_vars); + + $out.=$this->get_apps($query_vars); + } return $out; } @@ -204,46 +214,74 @@ class FDroid function get_apps($query_vars) { + $xml = simplexml_load_file($this->site_path."/repo/index.xml"); + $matches = $this->show_apps($xml,$query_vars,$numpages); + $out=''; - $out.='
'; - if($query_vars['fdfilter']===null) - $out.="All applications"; - else - $out.="Applications matching ".$query_vars['fdfilter']; - $out.="
"; + if(($query_vars['fdfilter']===null || $query_vars['fdfilter']!='') && $numpages>0) + { + $out.='
'; + if($query_vars['fdfilter']===null) + $out.="All applications"; + else + $out.='Applications matching "'.$query_vars['fdfilter'].'"'; + $out.="
"; - $out.='
'; - $out.='List | '; - $out.='Grid'; - $out.='
'; + $out.='
'; + $out.='List | '; + $out.='Grid'; + $out.='
'; - $out.='
'; - - $xml = simplexml_load_file($this->site_path."/repo/index.xml"); - $out.=$this->show_apps($xml,$query_vars,$numpages); - - $out.='

'; - if($query_vars['fdpage']==1) { - $out.="<<first "; - $out.="<prev "; - } else { - $out.='<<first '; - $out.='<<prev '; - } - $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; - if($query_vars['fdpage']==$numpages) { - $out.="next> "; - $out.="last>> "; - } else { - $out.='next> '; - $out.='last>> '; - } - $out.='

'; + $out.='
'; + } + + if($numpages>0) { + $out.=$matches; + + $out.='

'; + if($query_vars['fdpage']==1) { + $out.="<<first "; + $out.="<prev "; + } else { + $out.='<<first '; + $out.='<<prev '; + } + $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; + if($query_vars['fdpage']==$numpages) { + $out.="next> "; + $out.="last>> "; + } else { + $out.='next> '; + $out.='last>> '; + } + $out.='

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

No matches

'; + } return $out; } + + function show_search($query_vars) { + + $out=''; + $out.='
'; + $out.='

'; + $out.='

'; + + $out.=''; + foreach($query_vars as $name => $value) { + if($value !== null && $name != 'fdfilter') + $out.=''; + } + + $out.='
'."\n"; + + return $out; + } + function show_apps($xml,$query_vars,&$numpages) { @@ -283,11 +321,10 @@ class FDroid } } - if($query_vars['fdfilter']===null || stristr($appinfo['name'],$query_vars['fdfilter'])) { + if($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']))) { if($skipped<($query_vars['fdpage']-1)*$outputter->perpage) { $skipped++; } else if($got<$outputter->perpage) { - $out.=$outputter->outputEntry($query_vars, $appinfo); $got++; } From ef4f189a1a3a5fdb0b9a4d372b591f6930bd8cb0 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Thu, 22 Dec 2011 20:37:57 +0100 Subject: [PATCH 04/20] Redesigned the next/previous page switcher to allow direct access to any page. --- wp-fdroid/wp-fdroid.php | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 7d1b1dfc..2f1c253a 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -240,21 +240,31 @@ class FDroid $out.=$matches; $out.='

'; - if($query_vars['fdpage']==1) { - $out.="<<first "; - $out.="<prev "; - } else { - $out.='<<first '; - $out.='<<prev '; - } + + $out.='

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

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

No matches

'; From a9fd66cae20571a7061a670a54799f2874e0650d Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Thu, 22 Dec 2011 21:12:55 +0100 Subject: [PATCH 05/20] Searching now looks at the description of an app in addition to name and summary. --- wp-fdroid/wp-fdroid.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 7d1b1dfc..bf728ac8 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -315,13 +315,16 @@ class FDroid case "summary": $appinfo['summary']=$el; break; + case "description": + $appinfo['description']=$el; + break; case "license": $appinfo['license']=$el; break; } } - if($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']))) { + if($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']) || stristr($appinfo['description'],$query_vars['fdfilter']))) { if($skipped<($query_vars['fdpage']-1)*$outputter->perpage) { $skipped++; } else if($got<$outputter->perpage) { From 891f56b7020f3d5ec8aa664e0aaa5b167d67823f Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Fri, 23 Dec 2011 22:44:27 +0100 Subject: [PATCH 06/20] Basic raw permissions display for apps. --- wp-fdroid/wp-fdroid.php | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 7d1b1dfc..399251db 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -193,14 +193,39 @@ class FDroid $out.='Donate: '.$donate.'
'; $out.="

"; + $out.=''; + $out.="

Packages

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

Version ".$apk['version']." - "; $out.='download '; $out.=$apk['size']." bytes"; if($apk['srcname']) $out.='
source tarball'; - $out.="

"; + + if($i==0) + $divStyleDisplay='block'; + else + $divStyleDisplay='none'; + $divId='permissions'.$i; + $out.='

Permissions
'; + $out.='

'; + $permissions = explode(',',$apk['permissions']); + foreach($permissions as $permission) + $out.=$permission.'
'; + $out.='

'; + + $out.='

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

Index

'; From 59fa3f3a195686126497e6d1c09855abd074ca21 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Tue, 27 Dec 2011 20:28:39 +0100 Subject: [PATCH 07/20] Added an xml file from the Android source that lists all permissions and permission groups. --- wp-fdroid/AndroidManifest.xml | 1639 +++++++++++++++++++++++++++++++++ 1 file changed, 1639 insertions(+) create mode 100644 wp-fdroid/AndroidManifest.xml diff --git a/wp-fdroid/AndroidManifest.xml b/wp-fdroid/AndroidManifest.xml new file mode 100644 index 00000000..97658a11 --- /dev/null +++ b/wp-fdroid/AndroidManifest.xml @@ -0,0 +1,1639 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 34ae635f5031a04f98f9e69d2e3c8f805ff320fb Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Tue, 27 Dec 2011 20:29:45 +0100 Subject: [PATCH 08/20] Added functionality to parse android permission data from the appropriate XML file from the Android source. --- wp-fdroid/android-permissions.php | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 wp-fdroid/android-permissions.php diff --git a/wp-fdroid/android-permissions.php b/wp-fdroid/android-permissions.php new file mode 100644 index 00000000..9901a70c --- /dev/null +++ b/wp-fdroid/android-permissions.php @@ -0,0 +1,39 @@ +load($android_manifest_file_path); + + $xpath = new DOMXPath($doc); + + $description = ''; + + foreach ($xpath->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); + $permissions[$node->nodeName][$name]['description'] = str_replace(array("\r\n", "\r", "\n", "\t", ' '), '', $description); + + if($node->nodeName == 'permission') { + $permissions[$node->nodeName][$name]['permissionGroup'] = substr(strrchr($node->attributes->getNamedItem('permissionGroup')->value,'.'), 1); + $permissions[$node->nodeName][$name]['protectionLevel'] = $node->attributes->getNamedItem('protectionLevel')->value; + } + } + + // Cache descriptions from comments preceding the tags + if($node->nodeName == '#comment') { + $description .= $node->textContent; + } + elseif($node->nodeName != '#text') { + $description = ''; + } + } + + return $permissions; +} +?> \ No newline at end of file From 51d00edf86340ef12baaf44467fa1b05362c433a Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Wed, 28 Dec 2011 21:37:40 +0100 Subject: [PATCH 09/20] Added human readable labels and descriptions for permissions. The information is parsed from strings information from the Android source. This is really *much* to slow to do in real time, but a first step. Must be cached somehow. --- wp-fdroid/android-permissions.php | 53 +- wp-fdroid/strings.xml | 3389 +++++++++++++++++++++++++++++ 2 files changed, 3431 insertions(+), 11 deletions(-) create mode 100755 wp-fdroid/strings.xml diff --git a/wp-fdroid/android-permissions.php b/wp-fdroid/android-permissions.php index 9901a70c..17a2b31f 100644 --- a/wp-fdroid/android-permissions.php +++ b/wp-fdroid/android-permissions.php @@ -1,36 +1,67 @@ load($android_manifest_file_path); + $manifestDoc = new DOMDocument; + $manifestDoc->load($android_manifest_file_path); + $manifestXpath = new DOMXPath($manifestDoc); - $xpath = new DOMXPath($doc); - - $description = ''; + $stringsDoc = new DOMDocument; + $stringsDoc->load($android_strings_file_path); + $stringsXpath = new DOMXPath($stringsDoc); - foreach ($xpath->query('node()') as $node) { + $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); - $permissions[$node->nodeName][$name]['description'] = str_replace(array("\r\n", "\r", "\n", "\t", ' '), '', $description); + + // 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'] = $labelString; + $permissions[$node->nodeName][$name]['description'] = $descriptionString; + $permissions[$node->nodeName][$name]['comment'] = str_replace(array("\r\n", "\r", "\n", "\t", ' '), '', $comment); if($node->nodeName == 'permission') { - $permissions[$node->nodeName][$name]['permissionGroup'] = substr(strrchr($node->attributes->getNamedItem('permissionGroup')->value,'.'), 1); + $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') { - $description .= $node->textContent; + $comment .= $node->textContent; } elseif($node->nodeName != '#text') { - $description = ''; + $comment = ''; } } diff --git a/wp-fdroid/strings.xml b/wp-fdroid/strings.xml new file mode 100755 index 00000000..7b785ec5 --- /dev/null +++ b/wp-fdroid/strings.xml @@ -0,0 +1,3389 @@ + + + + + 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? + + From bb23e7fd4c13e8c2882175bc4663c4bb90ca94d4 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Wed, 28 Dec 2011 21:39:08 +0100 Subject: [PATCH 10/20] Human readable permissions texts. --- wp-fdroid/wp-fdroid.php | 43 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 399251db..6ac7d306 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -12,6 +12,8 @@ Revision history */ +include('android-permissions.php'); + class FDroid { @@ -101,8 +103,9 @@ class FDroid function get_app($query_vars) { + $permissions_data = get_android_permissions_array($this->site_path.'/repo/AndroidManifest.xml', $this->site_path.'/repo/strings.xml'); - $xml = simplexml_load_file($this->site_path."/repo/index.xml"); + $xml = simplexml_load_file($this->site_path.'/repo/index.xml'); foreach($xml->children() as $app) { $attrs=$app->attributes(); @@ -220,8 +223,42 @@ class FDroid $out.='

Permissions
'; $out.='

'; $permissions = explode(',',$apk['permissions']); - foreach($permissions as $permission) - $out.=$permission.'
'; + usort($permissions, + + + function ($a, $b) use (&$permissions_data) { + + $aProtectionLevel = $permissions_data['permission'][$a]['protectionLevel']; + $bProtectionLevel = $permissions_data['permission'][$b]['protectionLevel']; + + if($aProtectionLevel != $bProtectionLevel) { + return strcmp($aProtectionLevel, $bProtectionLevel); + } + + $aGroup = $permissions_data['permission'][$a]['permissionGroup']; + $bGroup = $permissions_data['permission'][$b]['permissionGroup']; + + return strcmp($aGroup, $bGroup); + } + + + + ); + + $permission_group_last = ''; + foreach($permissions as $permission) { + $permission_group = $permissions_data['permission'][$permission]['permissionGroup']; + if($permission_group != $permission_group_last) { + $out.=''.strtoupper($permissions_data['permission-group'][$permission_group]['label']).'
'; + $permission_group_last = $permission_group; + } + + $out.='('.strtoupper(substr($permissions_data['permission'][$permission]['protectionLevel'],0,1)).') - '; + $out.=''.$permissions_data['permission'][$permission]['label'].' ['.$permission.']
'; + $out.=$permissions_data['permission'][$permission]['description'].'
'; + //$out.=$permissions_data['permission'][$permission]['comment'].'
'; + $out.='
'; + } $out.='

'; $out.='

'; From e3af9bf78f64f73f9e2a4c86330083e1b12068f8 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Thu, 29 Dec 2011 19:45:18 +0100 Subject: [PATCH 11/20] Normalized indentation to use tab character and unix style line endings for the wp-fdroid plugin. This is consistent with the wordpress PHP source style. --- wp-fdroid/wp-fdroid.php | 908 ++++++++++++++++++++-------------------- 1 file changed, 454 insertions(+), 454 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 2168d76c..d4f09cd6 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -1,455 +1,455 @@ -inited=false; - $this->site_path=getenv('DOCUMENT_ROOT'); - } - - - // Register additional query variables. (Handler for the 'query_vars' filter) - function queryvars($qvars) { - $qvars[]='fdfilter'; - $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; - } - } - - // Santiy check query vars - if(!isset($query_vars['fdpage']) || !is_numeric($query_vars['fdpage']) || $query_vars['fdpage'] <= 0) { - $query_vars['fdpage'] = 1; - } - - $out = ''; - - if(isset($attribs['search']) && $query_vars['fdfilter']===null) { - $query_vars['fdfilter'] = ''; - } - - if($query_vars['fdid']!==null) { - $out.=$this->get_app($query_vars); - } else { - if($query_vars['fdfilter'] !== null) - $out.=$this->show_search($query_vars); - - $out.=$this->get_apps($query_vars); - } +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 "description": - $desc=$el; - break; - case "license": - $license=$el; - break; - case "source": - $source=$el; - break; - case "tracker": - $issues=$el; - break; - case "donate": - $donate=$el; - break; - case "web": - $web=$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 "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 "permissions": - $thisapk['permissions']=$pel; - break; - } - } - $apks[]=$thisapk; - - } - } - - $out='
'; - $out.='
'; - $out.='

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

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

".$desc."

"; - - $out.="

License: ".$license."

"; - - $out.="

"; - if(strlen($web)>0) - $out.='Website: '.$web.'
'; - if(strlen($issues)>0) - $out.='Issue Tracker: '.$issues.'
'; - if(strlen($source)>0) - $out.='Source Code: '.$source.'
'; - if($donate && strlen($donate)>0) - $out.='Donate: '.$donate.'
'; - $out.="

"; - - $out.="

Packages

"; - foreach($apks as $apk) { - $out.="

Version ".$apk['version']." - "; - $out.='download '; - $out.=$apk['size']." bytes"; - if($apk['srcname']) - $out.='
source tarball'; - $out.="

"; - } - - $out.='

Index

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

Application not found

"; - } - - - 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) - $out.="All applications"; - else - $out.='Applications matching "'.$query_vars['fdfilter'].'"'; - $out.="
"; - - $out.='
'; - $out.='List | '; - $out.='Grid'; - $out.='
'; - - $out.='
'; - } - - if($numpages>0) { - $out.=$matches; - - $out.='

'; - if($query_vars['fdpage']==1) { - $out.="<<first "; - $out.="<prev "; - } else { - $out.='<<first '; - $out.='<<prev '; - } - $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; - if($query_vars['fdpage']==$numpages) { - $out.="next> "; - $out.="last>> "; - } else { - $out.='next> '; - $out.='last>> '; - } - $out.='

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

No matches

'; - } - - return $out; - } - - - function show_search($query_vars) { - - $out=''; - $out.='
'; - $out.='

'; - $out.='

'; - - $out.=''; - foreach($query_vars as $name => $value) { - if($value !== null && $name != 'fdfilter') - $out.=''; - } - - $out.='
'."\n"; - - 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 "license": - $appinfo['license']=$el; - break; - } - } - - if($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']))) { - 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.='

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

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

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

\n"; - - $out.="
\n"; - - 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"; - } -} - -// 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(); - $vars=linkify(array_merge($query_vars, $params)); - 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.'='.$v.'&'; - } - return substr($retvar,0,-1); -} - - -$wp_fdroid = new FDroid(); - - -?> +Revision history +0.01 - 2010-12-04: Initial development version + +*/ + +class FDroid +{ + + // Our text domain, for internationalisation + private $textdom='wp-fdroid'; + + private $site_path; + + // Constructor + function FDroid() { + // Add filters etc here! + add_shortcode('fdroidrepo',array($this, 'do_shortcode')); + add_filter('query_vars',array($this, 'queryvars')); + $this->inited=false; + $this->site_path=getenv('DOCUMENT_ROOT'); + } + + + // Register additional query variables. (Handler for the 'query_vars' filter) + function queryvars($qvars) { + $qvars[]='fdfilter'; + $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; + } + } + + // Santiy check query vars + if(!isset($query_vars['fdpage']) || !is_numeric($query_vars['fdpage']) || $query_vars['fdpage'] <= 0) { + $query_vars['fdpage'] = 1; + } + + $out = ''; + + if(isset($attribs['search']) && $query_vars['fdfilter']===null) { + $query_vars['fdfilter'] = ''; + } + + if($query_vars['fdid']!==null) { + $out.=$this->get_app($query_vars); + } else { + if($query_vars['fdfilter'] !== null) + $out.=$this->show_search($query_vars); + + $out.=$this->get_apps($query_vars); + } + + return $out; + + } + + + function get_app($query_vars) { + + $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 "description": + $desc=$el; + break; + case "license": + $license=$el; + break; + case "source": + $source=$el; + break; + case "tracker": + $issues=$el; + break; + case "donate": + $donate=$el; + break; + case "web": + $web=$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 "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 "permissions": + $thisapk['permissions']=$pel; + break; + } + } + $apks[]=$thisapk; + + } + } + + $out='
'; + $out.='
'; + $out.='

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

"; + $out.="
"; + + $out.="

".$desc."

"; + + $out.="

License: ".$license."

"; + + $out.="

"; + if(strlen($web)>0) + $out.='Website: '.$web.'
'; + if(strlen($issues)>0) + $out.='Issue Tracker: '.$issues.'
'; + if(strlen($source)>0) + $out.='Source Code: '.$source.'
'; + if($donate && strlen($donate)>0) + $out.='Donate: '.$donate.'
'; + $out.="

"; + + $out.="

Packages

"; + foreach($apks as $apk) { + $out.="

Version ".$apk['version']." - "; + $out.='download '; + $out.=$apk['size']." bytes"; + if($apk['srcname']) + $out.='
source tarball'; + $out.="

"; + } + + $out.='

Index

'; + + return $out; + } + } + return "

Application not found

"; + } + + + 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) + $out.="All applications"; + else + $out.='Applications matching "'.$query_vars['fdfilter'].'"'; + $out.="
"; + + $out.='
'; + $out.='List | '; + $out.='Grid'; + $out.='
'; + + $out.='
'; + } + + if($numpages>0) { + $out.=$matches; + + $out.='

'; + if($query_vars['fdpage']==1) { + $out.="<<first "; + $out.="<prev "; + } else { + $out.='<<first '; + $out.='<<prev '; + } + $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; + if($query_vars['fdpage']==$numpages) { + $out.="next> "; + $out.="last>> "; + } else { + $out.='next> '; + $out.='last>> '; + } + $out.='

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

No matches

'; + } + + return $out; + } + + + function show_search($query_vars) { + + $out=''; + $out.='
'; + $out.='

'; + $out.='

'; + + $out.=''; + foreach($query_vars as $name => $value) { + if($value !== null && $name != 'fdfilter') + $out.=''; + } + + $out.='
'."\n"; + + 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 "license": + $appinfo['license']=$el; + break; + } + } + + if($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']))) { + 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.='

Details...'; + $out.="

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

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

\n"; + + $out.="
\n"; + + 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"; + } +} + +// 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(); + $vars=linkify(array_merge($query_vars, $params)); + 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.'='.$v.'&'; + } + return substr($retvar,0,-1); +} + + +$wp_fdroid = new FDroid(); + + +?> From cdcc6160bad2c5cbad0f3d4f0e2e90b0932ca4bc Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Tue, 3 Jan 2012 21:35:37 +0100 Subject: [PATCH 12/20] Better CSS for the page selector. --- wp-fdroid/wp-fdroid.php | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 2f1c253a..ac960785 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -241,30 +241,32 @@ class FDroid $out.='

'; - $out.='

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

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

No matches

'; From 88196e8b9b2c35230bee297e32c82b74c7597b34 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Tue, 10 Jan 2012 19:53:23 +0100 Subject: [PATCH 13/20] Human readable permission data will now be cached in serialized form for faster page generation. --- wp-fdroid/android-permissions.php | 37 +++++++++++++++++++++++++++++-- wp-fdroid/wp-fdroid.php | 2 +- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/wp-fdroid/android-permissions.php b/wp-fdroid/android-permissions.php index 17a2b31f..53e5c0c4 100644 --- a/wp-fdroid/android-permissions.php +++ b/wp-fdroid/android-permissions.php @@ -4,9 +4,37 @@ $android_manifest_file_path = 'AndroidManifest.xml'; // Path to the strings.xml-file from the Android source. Get it from https://raw.github.com/android/platform_frameworks_base/master/core/res/res/values/strings.xml for example. $android_strings_file_path = 'strings.xml'; -// Returns an associative array with android permissions and data about them -function get_android_permissions_array($android_manifest_file_path, $android_strings_file_path) { +$cache_file_path = 'android-permissions.cache'; +// Returns an associative array with android permissions and data about them +function get_android_permissions_array($android_manifest_file_path, $android_strings_file_path, $cache_file_path) { + + // Check status of cache + $android_manifest_file_stat = stat($android_manifest_file_path); + $android_manifest_file_mtime = $android_manifest_file_stat['mtime']; + $android_strings_file_stat = stat($android_strings_file_path); + $android_strings_file_mtime = $android_strings_file_stat['mtime']; + $cache_file_mtime = 0; + if(file_exists($cache_file_path)) { + $cache_file_stat = stat($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($cache_file_path, 'r'); + $cache_file_content = fread($cache_file_handle, filesize($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($cache_file_path); + + // Get permission raw data from XML $manifestDoc = new DOMDocument; $manifestDoc->load($android_manifest_file_path); $manifestXpath = new DOMXPath($manifestDoc); @@ -64,6 +92,11 @@ function get_android_permissions_array($android_manifest_file_path, $android_str $comment = ''; } } + + // Update cache with serialized permissions + $cache_file_handle = fopen($cache_file_path, 'w'); + fwrite($cache_file_handle, serialize($permissions)); + fclose($cache_file_handle); return $permissions; } diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 6ac7d306..34bc730a 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -103,7 +103,7 @@ class FDroid function get_app($query_vars) { - $permissions_data = get_android_permissions_array($this->site_path.'/repo/AndroidManifest.xml', $this->site_path.'/repo/strings.xml'); + $permissions_data = get_android_permissions_array($this->site_path.'/repo/AndroidManifest.xml', $this->site_path.'/repo/strings.xml', $this->site_path.'/repo/android-permissions.cache'); $xml = simplexml_load_file($this->site_path.'/repo/index.xml'); foreach($xml->children() as $app) { From 24da38c0f6a1922762d397c233eb46c370547b1f Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Wed, 11 Jan 2012 19:37:13 +0100 Subject: [PATCH 14/20] Strip slashes from descriptions/labels etc. --- wp-fdroid/android-permissions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wp-fdroid/android-permissions.php b/wp-fdroid/android-permissions.php index 53e5c0c4..c1c73c61 100644 --- a/wp-fdroid/android-permissions.php +++ b/wp-fdroid/android-permissions.php @@ -68,9 +68,9 @@ function get_android_permissions_array($android_manifest_file_path, $android_str $descriptionString = ucfirst($descriptionStringObject->item(0)->nodeValue); } - $permissions[$node->nodeName][$name]['label'] = $labelString; - $permissions[$node->nodeName][$name]['description'] = $descriptionString; - $permissions[$node->nodeName][$name]['comment'] = str_replace(array("\r\n", "\r", "\n", "\t", ' '), '', $comment); + $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'); From bd53c8bdc7721381a69d079c7ea672bd3cd318c0 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Wed, 11 Jan 2012 20:45:55 +0100 Subject: [PATCH 15/20] Slightly better layout of app packages + pseudo icons for permission protection level. --- wp-fdroid/wp-fdroid.php | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 34bc730a..7b33e4ff 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -209,18 +209,18 @@ class FDroid $out.="

Packages

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

Version ".$apk['version']." - "; - $out.='download '; + $out.="

Version ".$apk['version']."
"; + $out.='download apk '; $out.=$apk['size']." bytes"; if($apk['srcname']) $out.='
source tarball'; - if($i==0) + /*if($i==0) $divStyleDisplay='block'; - else + else*/ $divStyleDisplay='none'; $divId='permissions'.$i; - $out.='

Permissions
'; + $out.='
view permissions
'; $out.='

'; $permissions = explode(',',$apk['permissions']); usort($permissions, @@ -253,13 +253,13 @@ class FDroid $permission_group_last = $permission_group; } - $out.='('.strtoupper(substr($permissions_data['permission'][$permission]['protectionLevel'],0,1)).') - '; + $out.=$this->get_permission_protection_level_icon($permissions_data['permission'][$permission]['protectionLevel']).' '; $out.=''.$permissions_data['permission'][$permission]['label'].' ['.$permission.']
'; $out.=$permissions_data['permission'][$permission]['description'].'
'; //$out.=$permissions_data['permission'][$permission]['comment'].'
'; $out.='
'; } - $out.='

'; + $out.='
'; $out.='

'; $i++; @@ -273,6 +273,20 @@ class FDroid return "

Application not found

"; } + private function get_permission_protection_level_icon($protection_level) { + if($protection_level=='dangerous') + { + return ''; + } + elseif($protection_level=='normal') + { + return ''; + } + else + { + return '!'; + } + } function get_apps($query_vars) { From a7fac59c3b6f4b2220566204f372087d2d9de0be Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Thu, 12 Jan 2012 21:24:17 +0100 Subject: [PATCH 16/20] Added support for custom/extra/unknown permissions. Also alphabetic sorting of permissions with identical levels and group. --- wp-fdroid/wp-fdroid.php | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 7b33e4ff..8e073371 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -224,38 +224,42 @@ class FDroid $out.='
'; $permissions = explode(',',$apk['permissions']); usort($permissions, - - function ($a, $b) use (&$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']; - return strcmp($aGroup, $bGroup); - } + if($aGroup != $bGroup) { + return strcmp($aGroup, $bGroup); + } - - + return strcmp($a, $b); + } ); $permission_group_last = ''; foreach($permissions as $permission) { $permission_group = $permissions_data['permission'][$permission]['permissionGroup']; if($permission_group != $permission_group_last) { - $out.=''.strtoupper($permissions_data['permission-group'][$permission_group]['label']).'
'; + $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.']
'; - $out.=$permissions_data['permission'][$permission]['description'].'
'; + if($permissions_data['permission'][$permission]['description']) $out.=$permissions_data['permission'][$permission]['description'].'
'; //$out.=$permissions_data['permission'][$permission]['comment'].'
'; $out.='
'; } @@ -284,7 +288,7 @@ class FDroid } else { - return '!'; + return ''; } } From 044914777f619defcf30da0c75f3415181c86379 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Thu, 12 Jan 2012 21:27:32 +0100 Subject: [PATCH 17/20] Normalized indentation and eol. --- wp-fdroid/android-permissions.php | 204 +++--- wp-fdroid/wp-fdroid.php | 1072 ++++++++++++++--------------- 2 files changed, 638 insertions(+), 638 deletions(-) diff --git a/wp-fdroid/android-permissions.php b/wp-fdroid/android-permissions.php index c1c73c61..7e1288a9 100644 --- a/wp-fdroid/android-permissions.php +++ b/wp-fdroid/android-permissions.php @@ -1,103 +1,103 @@ -load($android_manifest_file_path); - $manifestXpath = new DOMXPath($manifestDoc); - - $stringsDoc = new DOMDocument; - $stringsDoc->load($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($cache_file_path, 'w'); - fwrite($cache_file_handle, serialize($permissions)); - fclose($cache_file_handle); - - return $permissions; -} +load($android_manifest_file_path); + $manifestXpath = new DOMXPath($manifestDoc); + + $stringsDoc = new DOMDocument; + $stringsDoc->load($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($cache_file_path, 'w'); + fwrite($cache_file_handle, serialize($permissions)); + fclose($cache_file_handle); + + return $permissions; +} ?> \ No newline at end of file diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 8e073371..e3ec52d5 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -1,536 +1,536 @@ -inited=false; - $this->site_path=getenv('DOCUMENT_ROOT'); - } - - - // Register additional query variables. (Handler for the 'query_vars' filter) - function queryvars($qvars) { - $qvars[]='fdfilter'; - $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; - } - } - - // Santiy check query vars - if(!isset($query_vars['fdpage']) || !is_numeric($query_vars['fdpage']) || $query_vars['fdpage'] <= 0) { - $query_vars['fdpage'] = 1; - } - - $out = ''; - - if(isset($attribs['search']) && $query_vars['fdfilter']===null) { - $query_vars['fdfilter'] = ''; - } - - if($query_vars['fdid']!==null) { - $out.=$this->get_app($query_vars); - } else { - if($query_vars['fdfilter'] !== null) - $out.=$this->show_search($query_vars); - - $out.=$this->get_apps($query_vars); - } - return $out; - - } - - - function get_app($query_vars) { - $permissions_data = get_android_permissions_array($this->site_path.'/repo/AndroidManifest.xml', $this->site_path.'/repo/strings.xml', $this->site_path.'/repo/android-permissions.cache'); - - $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 "description": - $desc=$el; - break; - case "license": - $license=$el; - break; - case "source": - $source=$el; - break; - case "tracker": - $issues=$el; - break; - case "donate": - $donate=$el; - break; - case "web": - $web=$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 "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 "permissions": - $thisapk['permissions']=$pel; - break; - } - } - $apks[]=$thisapk; - - } - } - - $out='
'; - $out.='
'; - $out.='

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

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

".$desc."

"; - - $out.="

License: ".$license."

"; - - $out.="

"; - if(strlen($web)>0) - $out.='Website: '.$web.'
'; - if(strlen($issues)>0) - $out.='Issue Tracker: '.$issues.'
'; - if(strlen($source)>0) - $out.='Source Code: '.$source.'
'; - if($donate && strlen($donate)>0) - $out.='Donate: '.$donate.'
'; - $out.="

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

Packages

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

Version ".$apk['version']."
"; - $out.='download apk '; - $out.=$apk['size']." bytes"; - if($apk['srcname']) - $out.='
source tarball'; - - /*if($i==0) - $divStyleDisplay='block'; - else*/ - $divStyleDisplay='none'; - $divId='permissions'.$i; - $out.='
view permissions
'; - $out.='

'; - $permissions = explode(',',$apk['permissions']); - usort($permissions, - function ($a, $b) use (&$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); - } - ); - - $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.='
'; - } - $out.='
'; - - $out.='

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

Index

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

Application not found

"; - } - - private function get_permission_protection_level_icon($protection_level) { - if($protection_level=='dangerous') - { - return ''; - } - elseif($protection_level=='normal') - { - return ''; - } - else - { - return ''; - } - } - - 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) - $out.="All applications"; - else - $out.='Applications matching "'.$query_vars['fdfilter'].'"'; - $out.="
"; - - $out.='
'; - $out.='List | '; - $out.='Grid'; - $out.='
'; - - $out.='
'; - } - - if($numpages>0) { - $out.=$matches; - - $out.='

'; - if($query_vars['fdpage']==1) { - $out.="<<first "; - $out.="<prev "; - } else { - $out.='<<first '; - $out.='<<prev '; - } - $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; - if($query_vars['fdpage']==$numpages) { - $out.="next> "; - $out.="last>> "; - } else { - $out.='next> '; - $out.='last>> '; - } - $out.='

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

No matches

'; - } - - return $out; - } - - - function show_search($query_vars) { - - $out=''; - $out.='
'; - $out.='

'; - $out.='

'; - - $out.=''; - foreach($query_vars as $name => $value) { - if($value !== null && $name != 'fdfilter') - $out.=''; - } - - $out.='
'."\n"; - - 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 "license": - $appinfo['license']=$el; - break; - } - } - - if($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']))) { - 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.='

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

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

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

\n"; - - $out.="
\n"; - - 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"; - } -} - -// 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(); - $vars=linkify(array_merge($query_vars, $params)); - 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.'='.$v.'&'; - } - return substr($retvar,0,-1); -} - - -$wp_fdroid = new FDroid(); - - -?> +inited=false; + $this->site_path=getenv('DOCUMENT_ROOT'); + } + + + // Register additional query variables. (Handler for the 'query_vars' filter) + function queryvars($qvars) { + $qvars[]='fdfilter'; + $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; + } + } + + // Santiy check query vars + if(!isset($query_vars['fdpage']) || !is_numeric($query_vars['fdpage']) || $query_vars['fdpage'] <= 0) { + $query_vars['fdpage'] = 1; + } + + $out = ''; + + if(isset($attribs['search']) && $query_vars['fdfilter']===null) { + $query_vars['fdfilter'] = ''; + } + + if($query_vars['fdid']!==null) { + $out.=$this->get_app($query_vars); + } else { + if($query_vars['fdfilter'] !== null) + $out.=$this->show_search($query_vars); + + $out.=$this->get_apps($query_vars); + } + return $out; + + } + + + function get_app($query_vars) { + $permissions_data = get_android_permissions_array($this->site_path.'/repo/AndroidManifest.xml', $this->site_path.'/repo/strings.xml', $this->site_path.'/repo/android-permissions.cache'); + + $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 "description": + $desc=$el; + break; + case "license": + $license=$el; + break; + case "source": + $source=$el; + break; + case "tracker": + $issues=$el; + break; + case "donate": + $donate=$el; + break; + case "web": + $web=$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 "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 "permissions": + $thisapk['permissions']=$pel; + break; + } + } + $apks[]=$thisapk; + + } + } + + $out='
'; + $out.='
'; + $out.='

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

"; + $out.="
"; + + $out.="

".$desc."

"; + + $out.="

License: ".$license."

"; + + $out.="

"; + if(strlen($web)>0) + $out.='Website: '.$web.'
'; + if(strlen($issues)>0) + $out.='Issue Tracker: '.$issues.'
'; + if(strlen($source)>0) + $out.='Source Code: '.$source.'
'; + if($donate && strlen($donate)>0) + $out.='Donate: '.$donate.'
'; + $out.="

"; + + $out.=''; + + $out.="

Packages

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

Version ".$apk['version']."
"; + $out.='download apk '; + $out.=$apk['size']." bytes"; + if($apk['srcname']) + $out.='
source tarball'; + + /*if($i==0) + $divStyleDisplay='block'; + else*/ + $divStyleDisplay='none'; + $divId='permissions'.$i; + $out.='
view permissions
'; + $out.='

'; + $permissions = explode(',',$apk['permissions']); + usort($permissions, + function ($a, $b) use (&$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); + } + ); + + $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.='
'; + } + $out.='
'; + + $out.='

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

Index

'; + + return $out; + } + } + return "

Application not found

"; + } + + private function get_permission_protection_level_icon($protection_level) { + if($protection_level=='dangerous') + { + return ''; + } + elseif($protection_level=='normal') + { + return ''; + } + else + { + return ''; + } + } + + 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) + $out.="All applications"; + else + $out.='Applications matching "'.$query_vars['fdfilter'].'"'; + $out.="
"; + + $out.='
'; + $out.='List | '; + $out.='Grid'; + $out.='
'; + + $out.='
'; + } + + if($numpages>0) { + $out.=$matches; + + $out.='

'; + if($query_vars['fdpage']==1) { + $out.="<<first "; + $out.="<prev "; + } else { + $out.='<<first '; + $out.='<<prev '; + } + $out.=' Page '.$query_vars['fdpage'].' of '.$numpages.' '; + if($query_vars['fdpage']==$numpages) { + $out.="next> "; + $out.="last>> "; + } else { + $out.='next> '; + $out.='last>> '; + } + $out.='

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

No matches

'; + } + + return $out; + } + + + function show_search($query_vars) { + + $out=''; + $out.='
'; + $out.='

'; + $out.='

'; + + $out.=''; + foreach($query_vars as $name => $value) { + if($value !== null && $name != 'fdfilter') + $out.=''; + } + + $out.='
'."\n"; + + 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 "license": + $appinfo['license']=$el; + break; + } + } + + if($query_vars['fdfilter']===null || $query_vars['fdfilter']!='' && (stristr($appinfo['name'],$query_vars['fdfilter']) || stristr($appinfo['summary'],$query_vars['fdfilter']))) { + 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.='

Details...'; + $out.="

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

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

\n"; + + $out.="
\n"; + + 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"; + } +} + +// 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(); + $vars=linkify(array_merge($query_vars, $params)); + 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.'='.$v.'&'; + } + return substr($retvar,0,-1); +} + + +$wp_fdroid = new FDroid(); + + +?> From 5f4a422b622260a00475a4daee37555e314ddd7c Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Thu, 12 Jan 2012 21:46:49 +0100 Subject: [PATCH 18/20] Wrapped the android permissions function in a class holding config variables. --- wp-fdroid/android-permissions.php | 197 ++++++++++++++++-------------- wp-fdroid/wp-fdroid.php | 3 +- 2 files changed, 106 insertions(+), 94 deletions(-) diff --git a/wp-fdroid/android-permissions.php b/wp-fdroid/android-permissions.php index 7e1288a9..6b8c2805 100644 --- a/wp-fdroid/android-permissions.php +++ b/wp-fdroid/android-permissions.php @@ -1,103 +1,114 @@ 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() { - // 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($cache_file_path, 'r'); - $cache_file_content = fread($cache_file_handle, filesize($cache_file_path)); + // 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($cache_file_path, 'w'); + fwrite($cache_file_handle, serialize($permissions)); 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($cache_file_path); - - // Get permission raw data from XML - $manifestDoc = new DOMDocument; - $manifestDoc->load($android_manifest_file_path); - $manifestXpath = new DOMXPath($manifestDoc); - - $stringsDoc = new DOMDocument; - $stringsDoc->load($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($cache_file_path, 'w'); - fwrite($cache_file_handle, serialize($permissions)); - fclose($cache_file_handle); - - return $permissions; } -?> \ No newline at end of file +?> diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index e3ec52d5..48ad80e0 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -103,7 +103,8 @@ class FDroid function get_app($query_vars) { - $permissions_data = get_android_permissions_array($this->site_path.'/repo/AndroidManifest.xml', $this->site_path.'/repo/strings.xml', $this->site_path.'/repo/android-permissions.cache'); + $permissions_object = new AndroidPermissions($this->site_path.'/repo/AndroidManifest.xml', $this->site_path.'/repo/strings.xml', $this->site_path.'/repo/android-permissions.cache'); + $permissions_data = $permissions_object->get_permissions_array(); $xml = simplexml_load_file($this->site_path.'/repo/index.xml'); foreach($xml->children() as $app) { From 82f5332af6229fb9e72371387621285ca7618ee1 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Thu, 12 Jan 2012 21:49:47 +0100 Subject: [PATCH 19/20] Removed executable permissions on strings.xml. *sigh* --- wp-fdroid/strings.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 wp-fdroid/strings.xml diff --git a/wp-fdroid/strings.xml b/wp-fdroid/strings.xml old mode 100755 new mode 100644 From a2569989b4529a5b56b1863f97aa6f889831f006 Mon Sep 17 00:00:00 2001 From: Hans-Emil Skogh Date: Sat, 14 Jan 2012 12:39:33 +0100 Subject: [PATCH 20/20] Handle if a package has no permissions. --- wp-fdroid/wp-fdroid.php | 98 +++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/wp-fdroid/wp-fdroid.php b/wp-fdroid/wp-fdroid.php index 729345b8..1fb3d1ac 100644 --- a/wp-fdroid/wp-fdroid.php +++ b/wp-fdroid/wp-fdroid.php @@ -215,55 +215,60 @@ class FDroid if($apk['srcname']) $out.='
source tarball'; - /*if($i==0) - $divStyleDisplay='block'; - else*/ - $divStyleDisplay='none'; - $divId='permissions'.$i; - $out.='
view permissions
'; - $out.='
'; - $permissions = explode(',',$apk['permissions']); - usort($permissions, - function ($a, $b) use (&$permissions_data) { + if(isset($apk['permissions'])) { + /*if($i==0) + $divStyleDisplay='block'; + else*/ + $divStyleDisplay='none'; + $divId='permissions'.$i; + $out.='
view permissions
'; + $out.='
'; + $permissions = explode(',',$apk['permissions']); + usort($permissions, + function ($a, $b) use (&$permissions_data) { - $aProtectionLevel = $permissions_data['permission'][$a]['protectionLevel']; - $bProtectionLevel = $permissions_data['permission'][$b]['protectionLevel']; + $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; + if($aProtectionLevel != $bProtectionLevel) { + if(strlen($aProtectionLevel)==0) return 1; + if(strlen($bProtectionLevel)==0) return -1; - return strcmp($aProtectionLevel, $bProtectionLevel); + 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); + } + ); + + $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; } - $aGroup = $permissions_data['permission'][$a]['permissionGroup']; - $bGroup = $permissions_data['permission'][$b]['permissionGroup']; - - if($aGroup != $bGroup) { - return strcmp($aGroup, $bGroup); - } - - return strcmp($a, $b); + $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.='
'; } - ); - - $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.='
'; + $out.='
'; + } + else { + $out.='
no permissions
'; } - $out.='
'; $out.='

'; $i++; @@ -278,16 +283,13 @@ class FDroid } private function get_permission_protection_level_icon($protection_level) { - if($protection_level=='dangerous') - { + if($protection_level=='dangerous') { return ''; } - elseif($protection_level=='normal') - { + elseif($protection_level=='normal') { return ''; } - else - { + else { return ''; } }