function getGeneratedUrls($plistFile) { global $config, $generatedUrls; if ($config["parsePlist"]) { $plistContent = parsePlist($plistFile); $ipaUrl = $plistContent["items"][0]["assets"][0]["url"]; $name = $plistContent["items"][0]["metadata"]["title"]; $plistUrl = pathinfo($ipaUrl, PATHINFO_DIRNAME) . "/" . pathinfo($ipaUrl, PATHINFO_FILENAME) . ".plist"; } else { // non-parsing plist version global $config, $generatedUrls; $name = pathinfo($plistFile, PATHINFO_FILENAME); $plistUrl = $config["baseUrl"] . $name . ".plist"; } $generatedUrls[$name] = "itms-services://?action=download-manifest&url=" . urlencode($plistUrl); }
protected function show() { // first get all the subdirectories, which do not have a file named "private" present if ($handle = opendir($this->appDirectory)) { while (($file = readdir($handle)) !== false) { if (in_array($file, array('.', '..')) || !is_dir($file) || glob($file . '/private')) { // skip if not a directory or has `private` file continue; } // now check if this directory has the 3 mandatory files $ipa = array_shift(glob($file . '/*.ipa')); $provisioningProfile = array_shift(glob($file . '/*.mobileprovision')); $plist = array_shift(glob($file . '/*.plist')); $note = array_shift(glob($file . '/*.html')); if (!$ipa || !$plist) { continue; } $plistDocument = new DOMDocument(); $plistDocument->load($plist); $parsed_plist = parsePlist($plistDocument); $newApp = array(); // now get the application name from the plist $newApp[self::INDEX_APP] = $parsed_plist['items'][0]['metadata']['title']; $newApp[self::INDEX_VERSION] = $parsed_plist['items'][0]['metadata']['bundle-version']; $newApp[self::INDEX_DIR] = $file; $newApp[self::INDEX_NOTES] = $note ? nl2br(file_get_contents($note)) : ''; if ($provisioningProfile) { $newApp[self::INDEX_PROFILE] = $provisioningProfile; $newApp[self::INDEX_PROFILE_UPDATE] = filectime($this->appDirectory . $provisioningProfile); } // add it to the array $this->applications[] = $newApp; } closedir($handle); } }
protected function show() { // first get all the subdirectories, which do not have a file named "private" present if ($handle = opendir($this->appDirectory)) { while (($file = readdir($handle)) !== false) { if (in_array($file, array('.', '..')) || !is_dir($this->appDirectory . $file) || glob($this->appDirectory . $file . '/private')) { // skip if not a directory or has `private` file continue; } // now check if this directory has the 3 mandatory files $ipa = @array_shift(glob($this->appDirectory.$file . '/*.ipa')); $provisioningProfile = @array_shift(glob($this->appDirectory.$file . '/*.mobileprovision')); $plist = @array_shift(glob($this->appDirectory.$file . '/*.plist')); $note = @array_shift(glob($this->appDirectory.$file . '/*.html')); $image = @array_shift(glob($this->appDirectory.$file . '/*.png')); if (!$ipa || !$plist) { continue; } $plistDocument = new DOMDocument(); $plistDocument->load($plist); $parsed_plist = parsePlist($plistDocument); $newApp = array(); // now get the application name from the plist $newApp[self::INDEX_APP] = $parsed_plist['items'][0]['metadata']['title']; if (array_key_exists('subtitle', $parsed_plist['items'][0]['metadata'])) $newApp[self::INDEX_SUBTITLE] = $parsed_plist['items'][0]['metadata']['subtitle']; $newApp[self::INDEX_VERSION] = $parsed_plist['items'][0]['metadata']['bundle-version']; $newApp[self::INDEX_DATE] = filectime($ipa); $newApp[self::INDEX_DIR] = $file; $newApp[self::INDEX_IMAGE] = substr($image, strpos($image, $file)); $newApp[self::INDEX_NOTES] = $note ? nl2br_skip_html(file_get_contents($note)) : ''; $newApp[self::INDEX_STATS] = array(); if ($provisioningProfile) { $newApp[self::INDEX_PROFILE] = $provisioningProfile; $newApp[self::INDEX_PROFILE_UPDATE] = filectime($provisioningProfile); } // now get the current user statistics $userlist = ""; $filename = $this->appDirectory."stats/".$file; $userlistfilename = $this->appDirectory."stats/userlist.txt"; if (file_exists($filename)) { $userlist = @file_get_contents($userlistfilename); $content = file_get_contents($filename); $lines = explode("\n", $content); foreach ($lines as $i => $line) : if ($line == "") continue; $device = explode(";;", $line); $newdevice = array(); $newdevice[self::DEVICE_USER] = $this->mapUser($device[0], $userlist); $newdevice[self::DEVICE_PLATFORM] = $this->mapPlatform($device[1]); $newdevice[self::DEVICE_OSVERSION] = $device[2]; $newdevice[self::DEVICE_APPVERSION] = $device[3]; $newdevice[self::DEVICE_LASTCHECK] = $device[4]; $newApp[self::INDEX_STATS][] = $newdevice; endforeach; // sort by app version $newApp[self::INDEX_STATS] = self::array_orderby($newApp[self::INDEX_STATS], self::DEVICE_APPVERSION, SORT_DESC, self::DEVICE_OSVERSION, SORT_DESC, self::DEVICE_PLATFORM, SORT_ASC, self::DEVICE_LASTCHECK, SORT_DESC); } // add it to the array $this->applications[] = $newApp; } closedir($handle); } }
return $dict; } function parse_array($arrayNode) { $array = array(); for ($node = $arrayNode->firstChild; $node != null; $node = $node->nextSibling) { if ($node->nodeType == XML_ELEMENT_NODE) { array_push($array, parseValue($node)); } } return $array; } $path = dirname(__FILE__) . "/" . $_REQUEST['file']; $plistDocument = new DOMDocument(); $plistDocument->load($path); $plistArray = parsePlist($plistDocument); $output = array(); // var_dump($plistArray['snippetsTE2']); foreach ($plistArray['snippetsTE2'] as $item) { $o = array(); $description = $item['label']; if ($description == '') { if ($item['snippetType'] == 3) { $description = '[unlabeled shell script]'; } elseif ($item['plainText']) { $description = substr($item['plainText'], 0, 25); } } $o['label'] = $description; $o['shortcut'] = $item['abbreviation']; array_push($output, $o);
public function show($appBundleIdentifier) { // first get all the subdirectories, which do not have a file named "private" present if ($handle = opendir($this->appDirectory)) { while (($file = readdir($handle)) !== false) { if (in_array($file, array('.', '..')) || !is_dir($this->appDirectory . $file) || glob($this->appDirectory . $file . '/private') && !$appBundleIdentifier && $this->logic != 'stats') { // skip if not a directory or has `private` file // but only if no bundle identifier is provided to this function continue; } // if a bundle identifier is provided and the directory does not match, continue if ($appBundleIdentifier && $file != $appBundleIdentifier) { continue; } // now check if this directory has the 3 mandatory files $files = $this->getApplicationVersions($file); if (count($files) == 0) { continue; } $current = $this->findPublicVersion($files[self::VERSIONS_SPECIFIC_DATA]); $ipa = isset($current[self::FILE_IOS_IPA]) ? $current[self::FILE_IOS_IPA] : null; $plist = isset($current[self::FILE_IOS_PLIST]) ? $current[self::FILE_IOS_PLIST] : null; $apk = isset($current[self::FILE_ANDROID_APK]) ? $current[self::FILE_ANDROID_APK] : null; $json = isset($current[self::FILE_ANDROID_JSON]) ? $current[self::FILE_ANDROID_JSON] : null; $note = isset($current[self::FILE_COMMON_NOTES]) ? $current[self::FILE_COMMON_NOTES] : null; $restrict = isset($current[self::FILE_VERSION_RESTRICT]) ? $current[self::FILE_VERSION_RESTRICT] : null; $profile = isset($files[self::VERSIONS_COMMON_DATA][self::FILE_IOS_PROFILE]) ? $files[self::VERSIONS_COMMON_DATA][self::FILE_IOS_PROFILE] : null; $image = isset($files[self::VERSIONS_COMMON_DATA][self::FILE_COMMON_ICON]) ? $files[self::VERSIONS_COMMON_DATA][self::FILE_COMMON_ICON] : null; if (!$ipa && !$apk) { continue; } // if this app version has any restrictions, don't show it on the web interface! // we make it easy for now and do not check if the data makes sense and has users assigned to the defined team names if ($restrict && strlen(file_get_contents($restrict)) > 0) { $current = $this->findPublicVersion($files); } $app = $ipa ? $ipa : $apk; $newApp = array(); $newApp['path'] = substr($app, strpos($app, $file)); $newApp[self::INDEX_DIR] = $file; $newApp[self::INDEX_IMAGE] = substr($image, strpos($image, $file)); $newApp[self::INDEX_NOTES] = $note ? Helper::nl2br_skip_html(file_get_contents($note)) : ''; $newApp[self::INDEX_STATS] = array(); if ($ipa) { // iOS application $plistDocument = new DOMDocument(); $plistDocument->load($plist); $parsed_plist = parsePlist($plistDocument); // now get the application name from the plist $newApp[self::INDEX_APP] = $parsed_plist['items'][0]['metadata']['title']; if (isset($parsed_plist['items'][0]['metadata']['subtitle']) && $parsed_plist['items'][0]['metadata']['subtitle']) { $newApp[self::INDEX_SUBTITLE] = $parsed_plist['items'][0]['metadata']['subtitle']; } $newApp[self::INDEX_VERSION] = $parsed_plist['items'][0]['metadata']['bundle-version']; $newApp[self::INDEX_DATE] = filectime($ipa); $newApp[self::INDEX_APPSIZE] = filesize($ipa); if ($profile) { $newApp[self::INDEX_PROFILE] = $profile; $newApp[self::INDEX_PROFILE_UPDATE] = filectime($profile); } $newApp[self::INDEX_PLATFORM] = self::APP_PLATFORM_IOS; } else { if ($apk) { // Android Application // parse the json file $parsed_json = json_decode(file_get_contents($json), true); // now get the application name from the json file $newApp[self::INDEX_APP] = $parsed_json['title']; $newApp[self::INDEX_SUBTITLE] = $parsed_json['versionName']; $newApp[self::INDEX_VERSION] = $parsed_json['versionCode']; $newApp[self::INDEX_NOTES] = $parsed_json['notes']; $newApp[self::INDEX_DATE] = filectime($apk); $newApp[self::INDEX_APPSIZE] = filesize($apk); $newApp[self::INDEX_PLATFORM] = self::APP_PLATFORM_ANDROID; } } // now get the current user statistics $filename = $this->appDirectory . "stats/" . $file; if (file_exists($filename)) { $users = self::parseUserList(); $lines = @file($filename, FILE_IGNORE_NEW_LINES); foreach ($lines as $i => $line) { if (!$line) { continue; } $device = explode(self::STATS_SEPARATOR, $line); $device[0] = strtolower($device[0]); // need case-insensitive match $newdevice = array(); $newdevice[self::DEVICE_USER] = isset($users[$device[0]]) ? $users[$device[0]]['name'] : '-'; $newdevice[self::DEVICE_PLATFORM] = Helper::mapPlatform(isset($device[1]) ? $device[1] : null); $newdevice[self::DEVICE_OSVERSION] = isset($device[2]) ? $device[2] : ''; $newdevice[self::DEVICE_APPVERSION] = isset($device[3]) ? $device[3] : ''; $newdevice[self::DEVICE_LASTCHECK] = isset($device[4]) ? $device[4] : ''; $newdevice[self::DEVICE_LANGUAGE] = isset($device[5]) ? $device[5] : ''; $newdevice[self::DEVICE_INSTALLDATE] = isset($device[6]) ? $device[6] : ''; $newdevice[self::DEVICE_USAGETIME] = isset($device[7]) ? $device[7] : ''; $newApp[self::INDEX_STATS][] = $newdevice; } // sort by app version $newApp[self::INDEX_STATS] = Helper::array_orderby($newApp[self::INDEX_STATS], self::DEVICE_APPVERSION, SORT_DESC, self::DEVICE_OSVERSION, SORT_DESC, self::DEVICE_PLATFORM, SORT_ASC, self::DEVICE_INSTALLDATE, SORT_DESC, self::DEVICE_LASTCHECK, SORT_DESC); } // add it to the array $this->applications[] = $newApp; } closedir($handle); } }
protected function deliverJSON($api, $files) { // check for available updates for the given bundleidentifier // and return a JSON string with the result values $current = current($files[self::VERSIONS_SPECIFIC_DATA]); $ipa = isset($current[self::FILE_IOS_IPA]) ? $current[self::FILE_IOS_IPA] : null; $plist = isset($current[self::FILE_IOS_PLIST]) ? $current[self::FILE_IOS_PLIST] : null; $note = isset($current[self::FILE_COMMON_NOTES]) ? $current[self::FILE_COMMON_NOTES] : null; if ($ipa && $plist) { // this is an iOS app if ($api == self::API_V1) { // this is API Version 1 $result = array(); // parse the plist file $plistDocument = new DOMDocument(); $plistDocument->load($plist); $parsed_plist = parsePlist($plistDocument); // get the bundle_version which we treat as build number $latestversion = $parsed_plist['items'][0]['metadata']['bundle-version']; // add the latest release notes if available if ($note) { $result[self::RETURN_NOTES] = Helper::nl2br_skip_html(file_get_contents($note)); } $result[self::RETURN_TITLE] = $parsed_plist['items'][0]['metadata']['title']; if (array_key_exists('subtitle', $parsed_plist['items'][0]['metadata']) && $parsed_plist['items'][0]['metadata']['subtitle']) { $result[self::RETURN_SUBTITLE] = $parsed_plist['items'][0]['metadata']['subtitle']; } $result[self::RETURN_RESULT] = $latestversion; return Helper::sendJSONAndExit($result); } else { // this is API Version 2 $result = array(); $appversion = Router::arg(self::PARAM_2_APP_VERSION) != null ? Router::arg(self::PARAM_2_APP_VERSION) : Router::arg(self::PARAM_1_APP_VERSION); foreach ($files[self::VERSIONS_SPECIFIC_DATA] as $version) { $ipa = $version[self::FILE_IOS_IPA]; $plist = $version[self::FILE_IOS_PLIST]; $note = $version[self::FILE_COMMON_NOTES]; $mandatory = isset($version[self::FILE_VERSION_MANDATORY]) ? $version[self::FILE_VERSION_MANDATORY] : null; // parse the plist file $plistDocument = new DOMDocument(); $plistDocument->load($plist); $parsed_plist = parsePlist($plistDocument); // get the bundle_version which we treat as build number $thisVersion = $parsed_plist['items'][0]['metadata']['bundle-version']; $newAppVersion = array(); // add the latest release notes if available if ($note) { $newAppVersion[self::RETURN_V2_NOTES] = Helper::nl2br_skip_html(file_get_contents($note)); } if ($mandatory) { $newAppVersion[self::RETURN_V2_MANDATORY] = true; } else { $newAppVersion[self::RETURN_V2_MANDATORY] = false; } $newAppVersion[self::RETURN_V2_TITLE] = $parsed_plist['items'][0]['metadata']['title']; if (array_key_exists('subtitle', $parsed_plist['items'][0]['metadata']) && $parsed_plist['items'][0]['metadata']['subtitle']) { $newAppVersion[self::RETURN_V2_SHORTVERSION] = $parsed_plist['items'][0]['metadata']['subtitle']; } $newAppVersion[self::RETURN_V2_VERSION] = $thisVersion; $newAppVersion[self::RETURN_V2_TIMESTAMP] = filectime($ipa); $newAppVersion[self::RETURN_V2_APPSIZE] = filesize($ipa); $result[] = $newAppVersion; } return Helper::sendJSONAndExit($result); } } Logger::log("no versions found: ios/deliverJSON"); return Helper::sendJSONAndExit(self::E_NO_VERSIONS_FOUND); }