diff --git a/CONTRIBS.md b/CONTRIBS.md index 54e0adf4..5e0e2a68 100644 --- a/CONTRIBS.md +++ b/CONTRIBS.md @@ -1,9 +1,9 @@ So far, these people have contributed: --------------------------------------- [Bananeweizen](https://github.com/Bananeweizen), [blakjakau](https://github.com/blakjakau), [boombuler](https://github.com/boombuler), +[breunigs](https://github.com/breunigs), [ccjon](https://github.com/ccjon), [cmrn](https://github.com/cmrn), [epf](https://github.com/epf), diff --git a/build.py b/build.py index 8d64942b..a7ace7e2 100755 --- a/build.py +++ b/build.py @@ -93,7 +93,7 @@ def loaderMD(var): payload = {'text': file, 'mode': 'markdown'} headers = {'Content-Type': 'application/json'} req = urllib2.Request(url, json.dumps(payload).encode('utf8'), headers) - md = urllib2.urlopen(req).read().decode('utf8').replace('\n', '').replace('\'', '\\\'') + md = urllib2.urlopen(req).read().decode('utf8').replace('\n', '\\n').replace('\'', '\\\'') files[fn] = {} files[fn][filemd5] = md db['files'] = files @@ -205,12 +205,24 @@ if buildMobile: if buildMobile not in ['debug','release']: raise Exception("Error: buildMobile must be 'debug' or 'release'") - # first, copy the IITC script into the mobile folder. create the folder if needed + # compile the user location script + fn = "user-location.user.js" + script = readfile("mobile/" + fn) + downloadUrl = distUrlBase and distUrlBase + '/' + fn.replace("\\","/") or 'none' + updateUrl = distUrlBase and downloadUrl.replace('.user.js', '.meta.js') or 'none' + script = doReplacements(script, downloadUrl=downloadUrl, updateUrl=updateUrl) + + metafn = fn.replace('.user.js', '.meta.js') + saveScriptAndMeta(script, os.path.join(outDir,fn), os.path.join(outDir,metafn)) + + # copy the IITC script into the mobile folder. create the folder if needed try: os.makedirs("mobile/assets") except: pass shutil.copy(os.path.join(outDir,"total-conversion-build.user.js"), "mobile/assets/iitc.js") + # copy the user location script into the mobile folder. + shutil.copy(os.path.join(outDir,"user-location.user.js"), "mobile/assets/user-location.user.js") # also copy plugins try: diff --git a/code/boot.js b/code/boot.js index 2982bd34..29b052cc 100644 --- a/code/boot.js +++ b/code/boot.js @@ -83,6 +83,26 @@ window.setupLayerChooserSelectOne = function() { }); } +// Setup the function to record the on/off status of overlay layerGroups +window.setupLayerChooserStatusRecorder = function() { + // Record already added layerGroups + $.each(window.layerChooser._layers, function(ind, chooserEntry) { + if(!chooserEntry.overlay) return true; + var display = window.map.hasLayer(chooserEntry.layer); + window.updateDisplayedLayerGroup(chooserEntry.name, display); + }); + + // Record layerGroups change + window.map.on('layeradd layerremove', function(e) { + var id = L.stamp(e.layer); + var layerGroup = this._layers[id]; + if (layerGroup && layerGroup.overlay) { + var display = (e.type === 'layeradd'); + window.updateDisplayedLayerGroup(layerGroup.name, display); + } + }, window.layerChooser); +} + window.setupStyles = function() { $('head').append('";return m.insertBefore(c.lastChild,m.firstChild)}function o(){var a=d.elements;return"string"==typeof a?a.split(" "):a}function n(a){var b=t[a[u]];b||(b={},p++,a[u]=p,t[p]=b);return b}function v(a,b,c){b||(b=f);if(e)return b.createElement(a);c||(c=n(b));b=c.cache[a]?c.cache[a].cloneNode():y.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a); +return b.canHaveChildren&&!z.test(a)?c.frag.appendChild(b):b}function A(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();a.createElement=function(c){return!d.shivMethods?b.createElem(c):v(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+o().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(d,b.frag)} +function w(a){a||(a=f);var b=n(a);if(d.shivCSS&&!q&&!b.hasCSS)b.hasCSS=!!s(a,"article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}");e||A(a,b);return a}function B(a){for(var b,c=a.attributes,m=c.length,f=a.ownerDocument.createElement(l+":"+a.nodeName);m--;)b=c[m],b.specified&&f.setAttribute(b.nodeName,b.nodeValue);f.style.cssText=a.style.cssText;return f}function x(a){function b(){clearTimeout(d._removeSheetTimer);c&&c.removeNode(!0); +c=null}var c,f,d=n(a),e=a.namespaces,j=a.parentWindow;if(!C||a.printShived)return a;"undefined"==typeof e[l]&&e.add(l);j.attachEvent("onbeforeprint",function(){b();var g,i,d;d=a.styleSheets;for(var e=[],h=d.length,k=Array(h);h--;)k[h]=d[h];for(;d=k.pop();)if(!d.disabled&&D.test(d.media)){try{g=d.imports,i=g.length}catch(j){i=0}for(h=0;h+~])("+o().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"); +for(k="$1"+l+"\\:$2";i--;)e=g[i]=g[i].split("}"),e[e.length-1]=e[e.length-1].replace(h,k),g[i]=e.join("}");e=g.join("{");i=a.getElementsByTagName("*");h=i.length;k=RegExp("^(?:"+o().join("|")+")$","i");for(d=[];h--;)g=i[h],k.test(g.nodeName)&&d.push(g.applyElement(B(g)));f=d;c=s(a,e)});j.attachEvent("onafterprint",function(){for(var a=f,c=a.length;c--;)a[c].removeNode();clearTimeout(d._removeSheetTimer);d._removeSheetTimer=setTimeout(b,500)});a.printShived=!0;return a}var r=j.html5||{},z=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i, +y=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q,u="_html5shiv",p=0,t={},e;(function(){try{var a=f.createElement("a");a.innerHTML="";q="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}e=b}catch(d){e=q=!0}})();var d={elements:r.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video", +version:"3.6.2",shivCSS:!1!==r.shivCSS,supportsUnknownElements:e,shivMethods:!1!==r.shivMethods,type:"default",shivDocument:w,createElement:v,createDocumentFragment:function(a,b){a||(a=f);if(e)return a.createDocumentFragment();for(var b=b||n(a),c=b.frag.cloneNode(),d=0,j=o(),l=j.length;darticle,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}"; +c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| +"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); +for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d @@ -53,9 +16,12 @@ function loadUserScriptHeader($path) + + + @@ -114,8 +80,10 @@ $pages = Array ( 'faq' => ' FAQ', 'desktop' => ' Desktop', 'mobile' => ' Mobile', + 'test' => ' Test Builds', 'developer' => ' Developers', 'about' => ' About', + 'donate' => ' Donate', ); $page = $_REQUEST['page']; @@ -137,7 +105,7 @@ foreach ( $pages as $key => $name ) print "$name\n"; # after 'mobile', add a horizontal seperator - if ( $key == 'mobile' ) + if ( $key == 'test' ) print "
  • "; } diff --git a/website/page/code/apk/ApkParser.php b/website/page/code/apk/ApkParser.php new file mode 100644 index 00000000..4f57de33 --- /dev/null +++ b/website/page/code/apk/ApkParser.php @@ -0,0 +1,76 @@ +apk = new ApkArchive($apkFile); + $this->manifest = new ApkManifest(new ApkXmlParser($this->apk->getManifestStream())); + } + + /** + * Get Manifest Object + * @return ApkManifest + */ + public function getManifest() + { + return $this->manifest; + } + + /** + * Get the apk. Zip handler. + * - Extract all(or sp. entries) files, + * - add file, + * - recompress + * - and other ZipArchive features. + * + * @return ApkArchive + */ + public function getApkArchive() + { + return $this->apk; + } + + /** + * Extract apk content directly + * + * @param mixed $destination + * @param array $entries + * @return bool + */ + public function extractTo($destination,$entries = NULL) + { + return $this->apk->extractTo($destination,$entries); + } +} \ No newline at end of file diff --git a/website/page/code/apk/lib/ApkAndroidPlatform.php b/website/page/code/apk/lib/ApkAndroidPlatform.php new file mode 100644 index 00000000..c696ec3d --- /dev/null +++ b/website/page/code/apk/lib/ApkAndroidPlatform.php @@ -0,0 +1,47 @@ + array('name' => 'Android 1.1 Platfrom'), + 3 => array('name' => 'Android 1.5 Platfrom'), + 4 => array('name' => 'Android 1.6 Platfrom'), + 5 => array('name' => 'Android 2.0 Platfrom'), + 6 => array('name' => 'Android 2.0.1 Platfrom'), + 7 => array('name' => 'Android 2.1 Platfrom'), + 8 => array('name' => 'Android 2.2 Platfrom'), + 9 => array('name' => 'Android 2.3 Platfrom'), + 10 => array('name' => 'Android 2.3.3 Platfrom'), + 10 => array('name' => 'Android 2.3.3 / 2.3.4 Platfroms'), + 11 => array('name' => 'Android 3.0 Platfroms'), + 12 => array('name' => 'Android 3.1 Platfroms'), + 13 => array('name' => 'Android 3.2 Platfroms'), + 14 => array('name' => 'Android 4.0 Platfroms'), + 14 => array('name' => 'Android 4.0.3 Platfroms'), + ); + + public function __construct($apiLevel) + { + $this->level = $apiLevel; + $this->platform = $this->getPlatform(); + } + + /** + * @return array + */ + public function getPlatform() + { + if(!isset(self::$platforms[$this->level])) + throw new Exception("Unknown api level."); + + $platform = self::$platforms[$this->level]; + $platform['level'] = $this->level; + return $platform; + } + +} \ No newline at end of file diff --git a/website/page/code/apk/lib/ApkArchive.php b/website/page/code/apk/lib/ApkArchive.php new file mode 100644 index 00000000..7be663f4 --- /dev/null +++ b/website/page/code/apk/lib/ApkArchive.php @@ -0,0 +1,117 @@ +getResource('file_name'), or getIcon() directly. + * @todo Override the // extractTo() method. Rewrite all of XML files converted from Binary Xml to text based XML! + */ + class ApkArchive extends ZipArchive + { + /** + * @var string + */ + private $filePath; + + /** + * @var string + */ + private $fileName; + + + public function __construct($file = false) + { + if($file && is_file($file)) + { + $this->open($file); + $this->fileName = basename($this->filePath = $file); + } + else + throw new Exception($file . " not a regular file"); + + } + + /** + * Get a file from apk Archive by name. + * + * @param string $name + * @param int $length + * @param int $flags + * @return mixed + */ + public function getFromName($name,$length = NULL,$flags = NULL) + { + if(strtolower(substr($name,-4)) == '.xml') + { + $xmlParser = new ApkXmlParser(new ApkStream($this->getStream($name))); + return $xmlParser->getXmlString(); + } + else + return parent::getFromName($name,$length,$flags); + } + + /** + * Returns an ApkStream whick contains AndroidManifest.xml + * @return ApkStream + */ + public function getManifestStream() + { + return new ApkStream($this->getStream('AndroidManifest.xml')); + } + + /** + * Apk file path. + * @return string + */ + public function getApkPath() + { + return $this->filePath; + } + + /** + * Apk file name + * @return string + */ + public function getApkName() + { + return $this->fileName; + } + + + public function extractTo($destination,$entries = NULL) + { + if($extResult = parent::extractTo($destination,$entries)) + { + //TODO: ApkXmlParser can not parse the main.xml and others! only AndroidManifest.xml + //return $extResult; + + $xmlFiles = $this->glob_recursive($destination . '/*.xml'); + + + foreach($xmlFiles as $xmlFile) + { + // TODO : Remove this ifcheck , if ApkXml can parse! amk! + if($xmlFile == "AndroidManifest.xml") + ApkXmlParser::decompressFile($xmlFile); + } + } + + return $extResult; + + } + + // Can Move to the Utils(???) class. + private function glob_recursive($pattern, $flags = 0) + { + $files = glob($pattern, $flags); + + foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) + { + $files = array_merge($files, $this->glob_recursive($dir.'/'.basename($pattern), $flags)); + } + + return $files; + } + + } diff --git a/website/page/code/apk/lib/ApkManifest.php b/website/page/code/apk/lib/ApkManifest.php new file mode 100644 index 00000000..1b070dc1 --- /dev/null +++ b/website/page/code/apk/lib/ApkManifest.php @@ -0,0 +1,269 @@ +xmlParser = $xmlParser; + } + + /** + * Returns ManifestXml as a String. + * @return string + */ + public function getXmlString() + { + return $this->xmlParser->getXmlString(); + } + + /** + * Get Application Permissions + * @return array + */ + public function getPermissions() + { + return $this->getXmlObject()->getPermissions(); + } + + /** + * Android Package Name + * @return string + */ + public function getPackageName() + { + return $this->getAttribute('package'); + } + + /** + * Application Version Name + * @return string + */ + public function getVersionName() + { + return $this->getAttribute('versionName'); + } + + /** + * Application Version Code + * @return mixed + */ + public function getVersionCode() + { + return hexdec( $this->getAttribute('versionCode') ); + } + + /** + * @return bool + */ + public function isDebuggable() + { + return (bool)$this->getAttribute('debuggable'); + } + + /** + * The minimum API Level required for the application to run. + * @return int + */ + public function getMinSdkLevel() + { + $xmlObj = $this->getXmlObject(); + $usesSdk = get_object_vars($xmlObj->{'uses-sdk'}); + return hexdec($usesSdk['@attributes']['minSdkVersion']); + } + + private function getAttribute($attributeName) + { + if($this->attrs === NULL) + { + $xmlObj = $this->getXmlObject(); + $vars = get_object_vars($xmlObj->attributes()); + $this->attrs = $vars['@attributes']; + } + + if(!isset($this->attrs[$attributeName])) + throw new Exception("Attribute not found : " . $attributeName); + + return $this->attrs[$attributeName]; + } + + /** + * More Information About The minimum API Level required for the application to run. + * @return ApkAndroidPlatform + */ + public function getMinSdk() + { + return new ApkAndroidPlatform($this->getMinSdkLevel()); + } + + /** + * get SimleXmlElement created from AndroidManifest.xml + * + * @param mixed $className + * @return ApkManifestXmlElement + */ + public function getXmlObject($className = 'ApkManifestXmlElement') + { + return $this->xmlParser->getXmlObject($className); + } + + /** + * Basicly string casting method. + */ + public function __toString() + { + return $this->getXmlString(); + } + + /** + * Android Permissions list + * @see http://developer.android.com/reference/android/Manifest.permission.html + * + * @todo: Move to {lang}_perms.php file, for easly translations. + * @var mixed + */ + public static $permissions = array( + 'ACCESS_CHECKIN_PROPERTIES' => 'Allows read/write access to the "properties" table in the checkin database, to change values that get uploaded.', + 'ACCESS_COARSE_LOCATION' => 'Allows an application to access coarse (e.g., Cell-ID, WiFi) location', + 'ACCESS_FINE_LOCATION' => 'Allows an application to access fine (e.g., GPS) location', + 'ACCESS_LOCATION_EXTRA_COMMANDS' => 'Allows an application to access extra location provider commands', + 'ACCESS_MOCK_LOCATION' => 'Allows an application to create mock location providers for testing', + 'ACCESS_NETWORK_STATE' => 'Allows applications to access information about networks', + 'ACCESS_SURFACE_FLINGER' => 'Allows an application to use SurfaceFlinger\'s low level features', + 'ACCESS_WIFI_STATE' => 'Allows applications to access information about Wi-Fi networks', + 'ACCOUNT_MANAGER' => 'Allows applications to call into AccountAuthenticators.', + 'ADD_VOICEMAIL' => 'Allows an application to add voicemails into the system.', + 'AUTHENTICATE_ACCOUNTS' => 'Allows an application to act as an AccountAuthenticator for the AccountManager', + 'BATTERY_STATS' => 'Allows an application to collect battery statistics', + 'BIND_APPWIDGET' => 'Allows an application to tell the AppWidget service which application can access AppWidget\'s data.', + 'BIND_DEVICE_ADMIN' => 'Must be required by device administration receiver, to ensure that only the system can interact with it.', + 'BIND_INPUT_METHOD' => 'Must be required by an InputMethodService, to ensure that only the system can bind to it.', + 'BIND_REMOTEVIEWS' => 'Must be required by a RemoteViewsService, to ensure that only the system can bind to it.', + 'BIND_TEXT_SERVICE' => 'Must be required by a TextService (e.g.', + 'BIND_VPN_SERVICE' => 'Must be required by an VpnService, to ensure that only the system can bind to it.', + 'BIND_WALLPAPER' => 'Must be required by a WallpaperService, to ensure that only the system can bind to it.', + 'BLUETOOTH' => 'Allows applications to connect to paired bluetooth devices', + 'BLUETOOTH_ADMIN' => 'Allows applications to discover and pair bluetooth devices', + 'BRICK' => 'Required to be able to disable the device (very dangerous!).', + 'BROADCAST_PACKAGE_REMOVED' => 'Allows an application to broadcast a notification that an application package has been removed.', + 'BROADCAST_SMS' => 'Allows an application to broadcast an SMS receipt notification', + 'BROADCAST_STICKY' => 'Allows an application to broadcast sticky intents.', + 'BROADCAST_WAP_PUSH' => 'Allows an application to broadcast a WAP PUSH receipt notification', + 'CALL_PHONE' => 'Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call being placed.', + 'CALL_PRIVILEGED' => 'Allows an application to call any phone number, including emergency numbers, without going through the Dialer user interface for the user to confirm the call being placed.', + 'CAMERA' => 'Required to be able to access the camera device.', + 'CHANGE_COMPONENT_ENABLED_STATE' => 'Allows an application to change whether an application component (other than its own) is enabled or not.', + 'CHANGE_CONFIGURATION' => 'Allows an application to modify the current configuration, such as locale.', + 'CHANGE_NETWORK_STATE' => 'Allows applications to change network connectivity state', + 'CHANGE_WIFI_MULTICAST_STATE' => 'Allows applications to enter Wi-Fi Multicast mode', + 'CHANGE_WIFI_STATE' => 'Allows applications to change Wi-Fi connectivity state', + 'CLEAR_APP_CACHE' => 'Allows an application to clear the caches of all installed applications on the device.', + 'CLEAR_APP_USER_DATA' => 'Allows an application to clear user data', + 'CONTROL_LOCATION_UPDATES' => 'Allows enabling/disabling location update notifications from the radio.', + 'DELETE_CACHE_FILES' => 'Allows an application to delete cache files.', + 'DELETE_PACKAGES' => 'Allows an application to delete packages.', + 'DEVICE_POWER' => 'Allows low-level access to power management', + 'DIAGNOSTIC' => 'Allows applications to RW to diagnostic resources.', + 'DISABLE_KEYGUARD' => 'Allows applications to disable the keyguard', + 'DUMP' => 'Allows an application to retrieve state dump information from system services.', + 'EXPAND_STATUS_BAR' => 'Allows an application to expand or collapse the status bar.', + 'FACTORY_TEST' => 'Run as a manufacturer test application, running as the root user.', + 'FLASHLIGHT' => 'Allows access to the flashlight', + 'FORCE_BACK' => 'Allows an application to force a BACK operation on whatever is the top activity.', + 'GET_ACCOUNTS' => 'Allows access to the list of accounts in the Accounts Service', + 'GET_PACKAGE_SIZE' => 'Allows an application to find out the space used by any package.', + 'GET_TASKS' => 'Allows an application to get information about the currently or recently running tasks: a thumbnail representation of the tasks, what activities are running in it, etc.', + 'GLOBAL_SEARCH' => 'This permission can be used on content providers to allow the global search system to access their data.', + 'HARDWARE_TEST' => 'Allows access to hardware peripherals.', + 'INJECT_EVENTS' => 'Allows an application to inject user events (keys, touch, trackball) into the event stream and deliver them to ANY window.', + 'INSTALL_LOCATION_PROVIDER' => 'Allows an application to install a location provider into the Location Manager', + 'INSTALL_PACKAGES' => 'Allows an application to install packages.', + 'INTERNAL_SYSTEM_WINDOW' => 'Allows an application to open windows that are for use by parts of the system user interface.', + 'INTERNET' => 'Allows applications to open network sockets.', + 'KILL_BACKGROUND_PROCESSES' => 'Allows an application to call killBackgroundProcesses(String).', + 'MANAGE_ACCOUNTS' => 'Allows an application to manage the list of accounts in the AccountManager', + 'MANAGE_APP_TOKENS' => 'Allows an application to manage (create, destroy, Z-order) application tokens in the window manager.', + 'MASTER_CLEAR' => '', + 'MODIFY_AUDIO_SETTINGS' => 'Allows an application to modify global audio settings', + 'MODIFY_PHONE_STATE' => 'Allows modification of the telephony state - power on, mmi, etc.', + 'MOUNT_FORMAT_FILESYSTEMS' => 'Allows formatting file systems for removable storage.', + 'MOUNT_UNMOUNT_FILESYSTEMS' => 'Allows mounting and unmounting file systems for removable storage.', + 'NFC' => 'Allows applications to perform I/O operations over NFC', + 'PERSISTENT_ACTIVITY' => 'This constant is deprecated. This functionality will be removed in the future; please do not use. Allow an application to make its activities persistent.', + 'PROCESS_OUTGOING_CALLS' => 'Allows an application to monitor, modify, or abort outgoing calls.', + 'READ_CALENDAR' => 'Allows an application to read the user\'s calendar data.', + 'READ_CONTACTS' => 'Allows an application to read the user\'s contacts data.', + 'READ_FRAME_BUFFER' => 'Allows an application to take screen shots and more generally get access to the frame buffer data', + 'READ_HISTORY_BOOKMARKS' => 'Allows an application to read (but not write) the user\'s browsing history and bookmarks.', + 'READ_INPUT_STATE' => 'Allows an application to retrieve the current state of keys and switches.', + 'READ_LOGS' => 'Allows an application to read the low-level system log files.', + 'READ_PHONE_STATE' => 'Allows read only access to phone state.', + 'READ_PROFILE' => 'Allows an application to read the user\'s personal profile data.', + 'READ_SMS' => 'Allows an application to read SMS messages.', + 'READ_SOCIAL_STREAM' => 'Allows an application to read from the user\'s social stream.', + 'READ_SYNC_SETTINGS' => 'Allows applications to read the sync settings', + 'READ_SYNC_STATS' => 'Allows applications to read the sync stats', + 'REBOOT' => 'Required to be able to reboot the device.', + 'RECEIVE_BOOT_COMPLETED' => 'Allows an application to receive the ACTION_BOOT_COMPLETED that is broadcast after the system finishes booting.', + 'RECEIVE_MMS' => 'Allows an application to monitor incoming MMS messages, to record or perform processing on them.', + 'RECEIVE_SMS' => 'Allows an application to monitor incoming SMS messages, to record or perform processing on them.', + 'RECEIVE_WAP_PUSH' => 'Allows an application to monitor incoming WAP push messages.', + 'RECORD_AUDIO' => 'Allows an application to record audio', + 'REORDER_TASKS' => 'Allows an application to change the Z-order of tasks', + 'RESTART_PACKAGES' => 'This constant is deprecated. The restartPackage(String) API is no longer supported.', + 'SEND_SMS' => 'Allows an application to send SMS messages.', + 'SET_ACTIVITY_WATCHER' => 'Allows an application to watch and control how activities are started globally in the system.', + 'SET_ALARM' => 'Allows an application to broadcast an Intent to set an alarm for the user.', + 'SET_ALWAYS_FINISH' => 'Allows an application to control whether activities are immediately finished when put in the background.', + 'SET_ANIMATION_SCALE' => 'Modify the global animation scaling factor.', + 'SET_DEBUG_APP' => 'Configure an application for debugging.', + 'SET_ORIENTATION' => 'Allows low-level access to setting the orientation (actually rotation) of the screen.', + 'SET_POINTER_SPEED' => 'Allows low-level access to setting the pointer speed.', + 'SET_PREFERRED_APPLICATIONS' => 'This constant is deprecated. No longer useful, see addPackageToPreferred(String) for details.', + 'SET_PROCESS_LIMIT' => 'Allows an application to set the maximum number of (not needed) application processes that can be running.', + 'SET_TIME' => 'Allows applications to set the system time', + 'SET_TIME_ZONE' => 'Allows applications to set the system time zone', + 'SET_WALLPAPER' => 'Allows applications to set the wallpaper', + 'SET_WALLPAPER_HINTS' => 'Allows applications to set the wallpaper hints', + 'SIGNAL_PERSISTENT_PROCESSES' => 'Allow an application to request that a signal be sent to all persistent processes', + 'STATUS_BAR' => 'Allows an application to open, close, or disable the status bar and its icons.', + 'SUBSCRIBED_FEEDS_READ' => 'Allows an application to allow access the subscribed feeds ContentProvider.', + 'SUBSCRIBED_FEEDS_WRITE' => '', + 'SYSTEM_ALERT_WINDOW' => 'Allows an application to open windows using the type TYPE_SYSTEM_ALERT, shown on top of all other applications.', + 'UPDATE_DEVICE_STATS' => 'Allows an application to update device statistics.', + 'USE_CREDENTIALS' => 'Allows an application to request authtokens from the AccountManager', + 'USE_SIP' => 'Allows an application to use SIP service', + 'VIBRATE' => 'Allows access to the vibrator', + 'WAKE_LOCK' => 'Allows using PowerManager WakeLocks to keep processor from sleeping or screen from dimming', + 'WRITE_APN_SETTINGS' => 'Allows applications to write the apn settings', + 'WRITE_CALENDAR' => 'Allows an application to write (but not read) the user\'s calendar data.', + 'WRITE_CONTACTS' => 'Allows an application to write (but not read) the user\'s contacts data.', + 'WRITE_EXTERNAL_STORAGE' => 'Allows an application to write to external storage', + 'WRITE_GSERVICES' => 'Allows an application to modify the Google service map.', + 'WRITE_HISTORY_BOOKMARKS' => 'Allows an application to write (but not read) the user\'s browsing history and bookmarks.', + 'WRITE_PROFILE' => 'Allows an application to write (but not read) the user\'s personal profile data.', + 'WRITE_SECURE_SETTINGS' => 'Allows an application to read or write the secure system settings.', + 'WRITE_SETTINGS' => 'Allows an application to read or write the system settings.', + 'WRITE_SMS' => 'Allows an application to write SMS messages.', + 'WRITE_SOCIAL_STREAM' => 'Allows an application to write (but not read) the user\'s social stream data.', + 'WRITE_SYNC_SETTINGS' => 'Allows applications to write the sync settings' + ); +} \ No newline at end of file diff --git a/website/page/code/apk/lib/ApkManifestXmlElement.php b/website/page/code/apk/lib/ApkManifestXmlElement.php new file mode 100644 index 00000000..c8a0f9af --- /dev/null +++ b/website/page/code/apk/lib/ApkManifestXmlElement.php @@ -0,0 +1,22 @@ +{'uses-permission'}; + + $perms = array(); + foreach($permsArray as $perm) + { + $permAttr = get_object_vars($perm); + $objNotationArray = explode('.',$permAttr['@attributes']['name']); + $permName = trim(end($objNotationArray)); + $perms[$permName] = ApkManifest::$permissions[$permName]; + } + + return $perms; + } + } diff --git a/website/page/code/apk/lib/ApkStream.php b/website/page/code/apk/lib/ApkStream.php new file mode 100644 index 00000000..a1df19ce --- /dev/null +++ b/website/page/code/apk/lib/ApkStream.php @@ -0,0 +1,88 @@ +stream = $stream; + } + + /** + * Read the next character from stream. + * + * @param mixed $length + */ + public function read($length = 1) + { + return fread($this->stream,$length); + } + + /** + * check if end of filestream + */ + public function feof() + { + return feof($this->stream); + } + + /** + * Jump to the index! + * @param int $offset + */ + public function seek($offset) + { + fseek($this->stream,$offset); + } + + /** + * Close the stream + */ + public function close() + { + fclose($this->stream); + } + + /** + * Read the next byte + * @return byte + */ + public function readByte() + { + return ord($this->read()); + } + + /** + * fetch the remaining byte into an array + * + * @param mixed $count Byte length. + * @return array + */ + public function getByteArray($count = null) + { + $bytes = array(); + + while(!$this->feof() && ($count === null || count($bytes) < $count)) + $bytes[] = $this->readByte(); + + return $bytes; + } + } + diff --git a/website/page/code/apk/lib/ApkXml.php b/website/page/code/apk/lib/ApkXml.php new file mode 100644 index 00000000..2c7f6a8a --- /dev/null +++ b/website/page/code/apk/lib/ApkXml.php @@ -0,0 +1,5 @@ +\r\n"; + private $bytes = array(); + private $ready = false; + + public static $indent_spaces = " "; + + /** + * Store the SimpleXmlElement object + * @var SimpleXmlElement + */ + private $xmlObject = NULL; + + + public function __construct(ApkStream $apkStream) + { + $this->bytes = $apkStream->getByteArray(); + } + + public static function decompressFile($file,$destination = NULL) + { + if(!is_file($file)) + throw new Exception("{$file} is not a regular file"); + + $parser = new self(new ApkStream(fopen($file,'rd'))); + //TODO : write a method in this class, ->saveToFile(); + file_put_contents($destination === NULL ? $file : $destination,$parser->getXmlString()); + } + + public function decompress() + { + $numbStrings = $this->littleEndianWord($this->bytes, 4*4); + $sitOff = 0x24; + $stOff = $sitOff + $numbStrings * 4; + $this->bytesTagOff = $this->littleEndianWord($this->bytes, 3*4); + + for ($ii = $this->bytesTagOff; $ii < count($this->bytes) - 4; $ii += 4): + if ($this->littleEndianWord($this->bytes, $ii) == self::START_TAG) : + $this->bytesTagOff = $ii; + break; + endif; + endfor; + + + + $off = $this->bytesTagOff; + $indentCount = 0; + $startTagLineNo = -2; + + while ($off < count($this->bytes)) + { + $currentTag = $this->littleEndianWord($this->bytes, $off); + $lineNo = $this->littleEndianWord($this->bytes, $off + 2*4); + $nameNsSi = $this->littleEndianWord($this->bytes, $off + 4*4); + $nameSi = $this->littleEndianWord($this->bytes, $off + 5*4); + + + switch($currentTag) + { + case self::START_TAG: + { + $tagSix = $this->littleEndianWord($this->bytes, $off + 6*4); + $numbAttrs = $this->littleEndianWord($this->bytes, $off + 7*4); + $off += 9*4; + $tagName = $this->compXmlString($this->bytes, $sitOff, $stOff, $nameSi); + $startTagLineNo = $lineNo; + $attr_string = ""; + + for ($ii=0; $ii < $numbAttrs; $ii++) + { + $attrNameNsSi = $this->littleEndianWord($this->bytes, $off); + $attrNameSi = $this->littleEndianWord($this->bytes, $off + 1*4); + $attrValueSi = $this->littleEndianWord($this->bytes, $off + 2*4); + $attrFlags = $this->littleEndianWord($this->bytes, $off + 3*4); + $attrResId = $this->littleEndianWord($this->bytes, $off + 4*4); + $off += 5*4; + + $attrName = $this->compXmlString($this->bytes, $sitOff, $stOff, $attrNameSi); + if($attrValueSi != 0xffffffff) + $attrValue = $this->compXmlString($this->bytes, $sitOff, $stOff, $attrValueSi); + else + $attrValue = "0x" . dechex($attrResId); + + $attr_string .= " " . $attrName . "=\"" . $attrValue . "\""; + + } + + $this->appendXmlIndent($indentCount, "<". $tagName . $attr_string . ">"); + $indentCount++; + } + break; + + case self::END_TAG: + { + $indentCount--; + $off += 6*4; + $tagName = $this->compXmlString($this->bytes, $sitOff, $stOff, $nameSi); + $this->appendXmlIndent($indentCount, ""); + } + break; + + case self::END_DOC_TAG: + { + $this->ready = true; + break 2; + } + break; + + default: + throw new Exception("Unrecognized tag code '" . dechex($currentTag) . "' at offset " . $off); + break; + } + + + } + + } + + public function compXmlString($xml, $sitOff, $stOff, $str_index) + { + if ($str_index < 0) + return null; + + $strOff = $stOff + $this->littleEndianWord($xml, $sitOff + $str_index * 4); + return $this->compXmlStringAt($xml, $strOff); + } + + public function appendXmlIndent($indent, $str) + { + $this->appendXml(substr(self::$indent_spaces,0, min($indent * 2, strlen(self::$indent_spaces))) . $str); + } + + public function appendXml($str) + { + $this->xml .= $str ."\r\n"; + } + + public function compXmlStringAt($arr, $string_offset) + { + $strlen = $arr[$string_offset + 1] << 8 & 0xff00 | $arr[$string_offset] & 0xff; + $string = ""; + + for ($i=0; $i<$strlen; $i++) + $string .= chr($arr[$string_offset + 2 + $i * 2]); + + return $string; + } + + public function littleEndianWord($arr, $off) + { + return $arr[$off+3] << 24&0xff000000 | $arr[$off+2] << 16&0xff0000 | $arr[$off+1]<<8&0xff00 | $arr[$off]&0xFF; + } + + public function output() + { + echo $this->getXmlString(); + } + + public function getXmlString() + { + if(!$this->ready) + $this->decompress(); + return $this->xml; + } + + public function getXmlObject($className = 'SimpleXmlElement') + { + if($this->xmlObject === NULL || !$this->xmlObject instanceof $className) + $this->xmlObject = simplexml_load_string($this->getXmlString(),$className); + + return $this->xmlObject; + } + } diff --git a/website/page/code/desktop-download.php b/website/page/code/desktop-download.php new file mode 100644 index 00000000..9845d07e --- /dev/null +++ b/website/page/code/desktop-download.php @@ -0,0 +1,64 @@ +.\2', $iitc_details['@version'] ); + + print "

    IITC version $iitc_version

    \n"; + + print "Download\n"; +} + + +function iitcDesktopPluginDownloadTable ( $build ) +{ +?> + + + + + + + + + + + +\n"; + + # remove 'IITC Plugin: ' prefix if it's there, for neatness + $name = preg_replace ( '/^IITC plugin: /i', '', $details['@name'] ); + + # format extended version info in less prominant font + $version = preg_replace ( '/^(\d+\.\d+\.\d+)\.(\d{8}\.\d{6})/', '\1.\2', $details['@version'] ); + + # remove unneeded prefix from description + $description = preg_replace ( '/^\[[^]]*\] */', '', $details['@description'] ); + + print ""; + print ""; + print ""; + print ""; + print "\n"; +} + +?> + +
    NameID / VersionDescriptionDownload
    $name$basename
    $version
    $descriptionDownload
    + + diff --git a/website/page/code/mobile-download.php b/website/page/code/mobile-download.php new file mode 100644 index 00000000..9a15e8de --- /dev/null +++ b/website/page/code/mobile-download.php @@ -0,0 +1,68 @@ +getManifest(); + + $result['apk_version'] = $manifest->getVersionName(); + + + $archive = $apkinfo->getApkArchive(); + $iitc_file = "assets/total-conversion-build.user.js"; + if ( $archive->statName ( $iitc_file ) === FALSE ); + $iitc_file = "assets/iitc.js"; + + $stream = $archive->getStream ( $iitc_file ); + + $header = loadUserScriptHeader ( $stream ); + + $result['iitc_version'] = $header['@version']; + + return $result; +} + +function iitcMobileDownload ( $apkfile ) +{ + + $version = getMobileVersion ( $apkfile ); + + $apk_version = $version['apk_version']; + $iitc_version = preg_replace ( '/^(\d+\.\d+\.\d+)\.(\d{8}\.\d{6})/', '\1.\2', $version['iitc_version'] ); + + # we need an absolute link for the QR Code + # get the URL of this page itself + $pageurl = ($_SERVER['HTTPS'] ? "https" : "http")."://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; + $apkurl = url_to_absolute ( $pageurl, $apkfile ); +?> + + +
    + +QR Code for download + +

    +IITC Mobile version , with IITC version +

    + +

    +Download or scan the QR Code +

    + +
    +
    + + + diff --git a/website/page/code/url/CHANGELOG.txt b/website/page/code/url/CHANGELOG.txt new file mode 100644 index 00000000..cb7d743f --- /dev/null +++ b/website/page/code/url/CHANGELOG.txt @@ -0,0 +1,24 @@ +Changelog +--------- + +absoluteurl v1.6, March 12, 2010 +--------------------------------- +- added encode_url function to convert an absolute url to its percentage + encoded equivalent, according to RFC 3986 + +absoluteurl v1.5, March 11, 2010 +--------------------------------- +- fixed to allow spaces in the path of url + +absoluteurl v1.4, October 2, 2009 +---------------------------------------------- +- Percentage encoding of the absolute url disabled. + +absoluteurl v1.2, 2009-02-27 +----------------------------------------------- +- Minor bug fix + + +absoluteurl v1.0, 2009-08-28 +---------------------------------------- +- Initial release \ No newline at end of file diff --git a/website/page/code/url/README.txt b/website/page/code/url/README.txt new file mode 100644 index 00000000..35f9c8d2 --- /dev/null +++ b/website/page/code/url/README.txt @@ -0,0 +1,26 @@ +absoluteurl +--------------------- + +This script converts the relative url to absolute url, provided a base url. + + +For more, look here: http://publicmind.in/blog/urltoabsolute + +Usage: +---------- + +Extract the script (url_to_absolute.php) into your web directory, include it into your current php file using: + +require(path-to-file); + +then, you can convert the relative url to absolute url by calling: + +url_to_absolute( $baseUrl, $relativeUrl); + +It return false on failure, otherwise returns the absolute url. If the $relativeUrl is a valid absolute url, it is returned without any modification. + +Author/credits +----------- + +1) Original author: David R. Nadeau, NadeauSoftware.com +2) Edited and maintained by: Nitin Kr, Gupta, publicmind.in \ No newline at end of file diff --git a/website/page/code/url/url_to_absolute.php b/website/page/code/url/url_to_absolute.php new file mode 100644 index 00000000..c6df5c24 --- /dev/null +++ b/website/page/code/url/url_to_absolute.php @@ -0,0 +1,485 @@ + '!%3A!ui', + "/" => '!%2F!ui', + "?" => '!%3F!ui', + "#" => '!%23!ui', + "[" => '!%5B!ui', + "]" => '!%5D!ui', + "@" => '!%40!ui', + "!" => '!%21!ui', + "$" => '!%24!ui', + "&" => '!%26!ui', + "'" => '!%27!ui', + "(" => '!%28!ui', + ")" => '!%29!ui', + "*" => '!%2A!ui', + "+" => '!%2B!ui', + "," => '!%2C!ui', + ";" => '!%3B!ui', + "=" => '!%3D!ui', + "%" => '!%25!ui', + ); + + $url = rawurlencode($url); + $url = preg_replace(array_values($reserved), array_keys($reserved), $url); + return $url; +} + +?> \ No newline at end of file diff --git a/website/page/code/userscript.php b/website/page/code/userscript.php new file mode 100644 index 00000000..c229df76 --- /dev/null +++ b/website/page/code/userscript.php @@ -0,0 +1,35 @@ + diff --git a/website/page/desktop.php b/website/page/desktop.php index b6ffa30d..cbc37976 100644 --- a/website/page/desktop.php +++ b/website/page/desktop.php @@ -1,9 +1,7 @@

    IITC Browser Addon

    NOTE: the $path build is currently selected. Return to the standard build."; +include_once ( "code/desktop-download.php" ); ?>
    @@ -51,16 +49,9 @@ Check your browser documentation for details on installing userscripts.

    Download

    .\2', $iitc_details['@version'] ); +iitcDesktopDownload ( "release" ); ?> -

    -IITC version -

    - -Download -
    @@ -71,47 +62,6 @@ Plugins extend/modify the IITC experience. You do not need to install all a minority of users.

    - - - - - - - - - - - \n"; - - # remove 'IITC Plugin: ' prefix if it's there, for neatness - $name = preg_replace ( '/^IITC plugin: /i', '', $details['@name'] ); - - # format extended version info in less prominant font - $version = preg_replace ( '/^(\d+\.\d+\.\d+)\.(\d{8}\.\d{6})/', '\1.\2', $details['@version'] ); - - # remove unneeded prefix from description - $description = preg_replace ( '/^\[[^]]*\] */', '', $details['@description'] ); - - print ""; - print ""; - print ""; - print ""; - -# print "".$details['@name']."$name - version ".$details['@version'].":
    \n"; -# print $details['@description']; - - print "\n"; -} - +iitcDesktopPluginDownloadTable ( "release" ); ?> - -
    NameID / VersionDescriptionDownload
    $name$basename
    $version
    $descriptionDownload
    - diff --git a/website/page/donate.php b/website/page/donate.php new file mode 100644 index 00000000..0bb4de13 --- /dev/null +++ b/website/page/donate.php @@ -0,0 +1,55 @@ +

    Donate

    + +

    +Thank you for wanting to support IITC. The developers have +discussed this +and decided that we would prefer you make donations to charity. +

    + + +

    +Our current suggestions are: +

    + +
    + + FSF Logo + +
    +

    Free Software Foundation

    +

    + The FSF is a nonprofit with a worldwide mission to promote + computer user freedom and to defend the rights of all free software users. [more] +

    +

    + Donate to the FSF. +

    +
    +
    + +
    + + EFF Logo + +
    +

    Electronic Frontier Foundation

    +

    + The EFF: +

      +
    • Defend free speech for bloggers, journalists, dissidents and ordinary people online.
    • +
    • Protect your privacy by fighting warrantless electronic searches and surveillance.
    • +
    • Advocate for copyright and patent laws that promote rather than chill innovation.
    • +
    • Educate the public about policy and legislation that threaten online freedom around the world, such as SOPA, ACTA, and TPP.
    • +
    + [more] +

    +

    + Donate to the EFF. +

    +
    +
    + + +

    + +

    diff --git a/website/page/mobile.php b/website/page/mobile.php index 86128735..8b6c1bb3 100644 --- a/website/page/mobile.php +++ b/website/page/mobile.php @@ -36,9 +36,26 @@ IITC Mobile is still in the early stages of development. Many things do not yet

    Download

    -

    -IITC Mobile version 0.3 (with IITC version 0.11.2). -

    +Download +include_once ( "code/mobile-download.php" ); +$apkfile = "mobile/IITC-Mobile-0.3.apk"; + + +if ( file_exists($apkfile) ) +{ + iitcMobileDownload ( $apkfile ); +} +else +{ + print "
    Error: $apkfile not found
    \n"; +} + +?> + + +
    +As IITC Mobile is regularly updated, you may want to consider trying the latest +test build. +
    diff --git a/website/page/test.php b/website/page/test.php new file mode 100644 index 00000000..e16a0f3b --- /dev/null +++ b/website/page/test.php @@ -0,0 +1,81 @@ +

    Test Builds

    + +

    +These test builds are made available for those who would like to try the latest development code without +needing to build it yourself. Automated scripts should update these builds within an hour of a change being +committed to Github. +

    + +
    +Test builds are built automatically. They could be broken at any time. If you have any doubts about using +unstable software, please use the standard desktop or mobile +builds. +
    + +NOTE: A non-standard test build, $path, is currently selected. The notes may not apply! Return to the standard test build.
    "; + + +$timestamp_file = $path . "/.build-timestamp"; +if ( file_exists ( $timestamp_file ) ) +{ + $build_time = file_get_contents ( $timestamp_file ); + + print "
    The current test build was built at $build_time
    "; +} +else +{ +} + +?> + +

    Desktop test build

    + + + +
    + + +

    Desktop test plugins

    + + + +
    + +

    Mobile test build

    + +Error: $apkfile not found\n"; +} + + +?> + + +