// // Alternatively, the contents of this file may be used under the terms of // either the GNU General Public License Version 2 or later (the "GPL"), or // the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), // in which case the provisions of the GPL or the LGPL are applicable instead // of those above. If you wish to allow use of your version of this file only // under the terms of either the GPL or the LGPL, and not to allow others to // use your version of this file under the terms of the MPL, indicate your // decision by deleting the provisions above and replace them with the notice // and other provisions required by the GPL or the LGPL. If you do not delete // the provisions above, a recipient may use your version of this file under // the terms of any one of the MPL, the GPL or the LGPL. // // ***** END LICENSE BLOCK ***** /** * AUS main script. * @package aus * @subpackage docs * @author Mike Morgan * * This script handles incoming requests, reads the related build * snippet and returns a properly formatted XML file for testing. */ // Require config and supporting libraries. require_once('./inc/init.php'); // Instantiate XML object. $xml = new Xml(); //Are we behind a proxy and given the IP via an alternate enviroment variable? If so, use it. if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) { list($ip) = explode(', ',$_SERVER["HTTP_X_FORWARDED_FOR"]); } else { $ip = $_SERVER["REMOTE_ADDR"]; } //We need to give the user a unique cookie and make it expire in 5 years. if (!array_key_exists(COOKIE_NAME, $_COOKIE)) { setcookie(COOKIE_NAME, $ip . '.' . microtime(true), time() + 157784630, '/', COOKIE_DOMAIN); } // Find everything between our CWD and 255 in QUERY_STRING. $rawPath = substr(urldecode($_SERVER['QUERY_STRING']),5,255); // Munge he resulting string and store it in $path. $path = explode('/',$rawPath); // Check to see if the user is requesting channel changing. if ( !(empty($_GET['newchannel']))) { $newchannel = $_GET['newchannel']; } // Determine incoming request and clean inputs. $clean = Array(); $clean['updateVersion'] = isset($path[0]) ? intval($path[0]) : null; $clean['product'] = isset($path[1]) ? trim($path[1]) : null; $clean['version'] = isset($path[2]) ? urlencode($path[2]) : null; $clean['build'] = isset($path[3]) ? trim($path[3]) : null; $clean['platform'] = isset($path[4]) ? trim($path[4]) : null; $clean['locale'] = isset($path[5]) ? trim($path[5]) : null; $clean['channel'] = isset($path[6]) ? trim($path[6]) : null; $clean['platformVersion'] = isset($path[7]) ? trim($path[7]) : null; $clean['dist'] = isset($path[8]) ? trim($path[8]) : null; $clean['distVersion'] = isset($path[9]) ? trim($path[9]) : null; $clean['newchannel'] = isset($newchannel) ? trim($newchannel) : null; // Check to see if we have a beta on PPC, and if so don't update since beta 4 // doesn't work on PPC. See bug 588412. if ( $clean['product'] == 'Firefox' && (preg_match('/^4\.0.*$/', $clean['version']) || preg_match('/^3\.7.*$/', $clean['version'])) && strpos($_SERVER['HTTP_USER_AGENT'], 'PPC')) { $xml->printXml(); exit; } // Check to see if the user is explicitly requesting an update. If they are, // skip throttling. If they aren't, and throttling is enabled, first check // explicit throttling. If no specific rules exist, fallback to global rules. // In either case, updates will be served based on the configured random seed. if ( (empty($_GET['force']) || $_GET['force']!=1) ) { // Default to false. If conditions are met, flip it. $throttleMe = false; $aus = new AUS_Object(); // Check explicit throttling. if ( !$aus->isThrottleException($clean['version'], $clean['channel']) ) { // check if locale based throttling is set. Do not use product based throttling if set if ( isset($localeThrottling[$clean['product']][$clean['version']][$clean['locale']]) ) { if ( mt_rand(0,99) >= $localeThrottling[$clean['product']][$clean['version']][$clean['locale']] ){ $throttleMe = true; } } elseif ( isset($productThrottling[$clean['product']][$clean['version']]) && mt_rand(0,99) >= $productThrottling[$clean['product']][$clean['version']] ) { $throttleMe = true; } // Check global throttling. } elseif ( defined('THROTTLE_GLOBAL') && THROTTLE_GLOBAL && defined('THROTTLE_LEVEL') && mt_rand(0,99) >= THROTTLE_LEVEL ) { $throttleMe = true; } if ($throttleMe) { if (defined('THROTTLE_LOGGING') && THROTTLE_LOGGING) { error_log('AUS2 THROTTLE: '.$ip.' '.$_SERVER['REQUEST_URI']); } $xml->printXml(); exit; } } // Connect to memcache and try to pull output. $memcache = new Memcaching(); $_cached_xml = $memcache->get($rawPath); if ($_cached_xml) { $xml = $_cached_xml; } else { /** * For each updateVersion, we will run separate code when it differs. * Our case statements below are ordered by date added, desc (recent ones first). * * If the only difference is an added parameter, etc., then we may blend cases * together by omitting a break. */ switch ($clean['updateVersion']) { /* * This is for the fifth revision, adding %PLATFORM_VERSION%. * /update/4/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/%PLATFORM_VERSION%/update.xml */ case 4: // Nothing special. /* * This is for the fourth revision, adding %DISTRIBUTION% and * %DISTRIBUTION_VERSION%. * /update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml */ case 3: // Nothing special. /* * This is for the third revision of the URI schema, with %OS_VERSION%. * /update2/2/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/update.xml */ case 2: // Check for OS_VERSION values and scrub the URI to make sure we aren't getting a malformed request // from a client suffering from bug 360127. if (empty($clean['platformVersion']) || $clean['platformVersion']=='%OS_VERSION%' || preg_match('/^1\.5.*$/',$clean['version'])) { break; } /* * This is for the second revision of the URI schema, with %CHANNEL% added. * /update2/1/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/update.xml */ case 1: // Set a default for platformVersion. if (empty($clean['platformVersion'])) { $clean['platformVersion'] = null; } // Check for a set channel. // Instantiate Update object and set updateVersion. $update = new Update(); // Instantiate our complete patch. $completePatch = new Patch($productBranchVersions,$nightlyChannels,'complete',$latestRelease); $channel = $clean['channel']; if (isset($clean['newchannel'])) { $completePatch->setChangingChannel(true); $channel = $clean['newchannel']; } // If our complete patch exists and is valid, set the patch line. if ($completePatch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],$channel) && $completePatch->isPatch()) { // Set our patchLine. $xml->setPatchLine($completePatch); // If available, pull update information from the build snippet. // FIXME hasUpdateInfo not used by snippet schema v2, needs refactoring if ($completePatch->hasUpdateInfo()) { $update->setVersion($completePatch->updateVersion); $update->setExtensionVersion($completePatch->updateExtensionVersion); } if (isset($completePatch->build)) { $update->setBuild($completePatch->build); } // If there is details url information, add it to the update object. if ($completePatch->hasDetailsUrl()) { $update->setDetails($completePatch->detailsUrl); } // If we found an update type, pass it along. if ($completePatch->hasUpdateType()) { $update->setType($completePatch->updateType); } // If we have a license URL, pass it along. if ($completePatch->hasLicenseUrl()) { $update->setLicense($completePatch->licenseUrl); } // If we have a billboard URL, pass it along. if ($completePatch->hasBillboardUrl()) { $update->setBillboard($completePatch->billboardURL); } // If showPrompt is set, pass it along. if ($completePatch->hasShowPrompt()) { $update->setShowPrompt($completePatch->showPrompt); } // If showNeverForVersion is set, pass it along. if ($completePatch->hasShowNeverForVersion()) { $update->setShowNeverForVersion($completePatch->showNeverForVersion); } // If showSurvey is set, pass it along. if ($completePatch->hasShowSurvey()) { $update->setShowSurvey($completePatch->showSurvey); } // If actions is set, pass it along. if ($completePatch->hasActions()) { $update->setActions($completePatch->actions); } // If we have a open URL, pass it along. if ($completePatch->hasOpenUrl()) { $update->setOpen($completePatch->openURL); } // If we have a notification URL, pass it along. if ($completePatch->hasNotificationUrl()) { $update->setNotification($completePatch->notificationURL); } // If we have a alert URL, pass it along. if ($completePatch->hasAlertUrl()) { $update->setAlert($completePatch->alertURL); } // If we have prompt wait time, pass it along. if ($completePatch->hasPromptWaitTime()) { $update->setPromptWaitTime($completePatch->promptWaitTime); } // If we have a display version, pass it along. if ($completePatch->hasDisplayVersion()) { $update->setDisplayVersion($completePatch->displayVersion); } // If we have an app version, pass it along. if ($completePatch->hasAppVersion()) { $update->setAppVersion($completePatch->appVersion); } // If we have a platform version, pass it along. if ($completePatch->hasPlatformVersion()) { $update->setPlatformVersion($completePatch->platformVersion); } // If we have a snippet schema version, pass it along. if ($completePatch->hasSnippetSchemaVersion()) { $update->setSnippetSchemaVersion($completePatch->snippetSchemaVersion); } } // if we are channel-switching, do not check for partial updates. if (!isset($clean['newchannel'])) { // Instantiate our partial patch. $partialPatch = new Patch($productBranchVersions,$nightlyChannels,'partial'); // If our partial patch exists and is valid, set the patch line. if ($partialPatch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],$clean['channel']) && $partialPatch->isPatch() && $partialPatch->isOneStepFromLatest($completePatch->build)) { $xml->setPatchLine($partialPatch); } } // If we have valid patchLine(s), set up our output. if ($xml->hasPatchLine() && $completePatch->isSupported($completePatch->updateType, $clean['product'], $completePatch->updateExtensionVersion, $clean['platformVersion'], $unsupportedPlatforms)) { $xml->startUpdate($update); $xml->drawPatchLines(); $xml->endUpdate(); } break; /* * This is for the first revision of the URI schema. * /update2/0/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/update.xml */ case 0: default: // Instantiate Update object and set updateVersion. $update = new Update(); // Instantiate Patch object and set Path based on passed args. $patch = new Patch($productBranchVersions,$nightlyChannels,'complete'); $patch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],null); if ($patch->isPatch()) { $xml->setPatchLine($patch); } // If we have a new build, draw the update block and patch line. // If there is no valid patch file, client will receive no updates by default. if ($xml->hasPatchLine()) { $xml->startUpdate($update); $xml->drawPatchLines(); $xml->endUpdate(); } break; } } // If we are debugging output plaintext and exit. if ( defined('DEBUG') && DEBUG == true ) { echo ''."\n"; echo ''."\n"; echo ''."\n"; echo 'AUS Debug Information'."\n"; echo ''."\n"; echo ''."\n"; echo '

AUS Debug Information

'."\n"; echo '

XML Output

'."\n"; echo '
'."\n";
    echo htmlentities($xml->getOutput());
    echo '
'."\n"; if (!empty($clean)) { echo '

Inputs

'."\n"; echo '
'."\n";
        print_r($clean);
        echo '
'."\n"; } echo '

Patch Objects

'."\n"; echo '
'."\n";
    if (!empty($patch)) {
        print_r($patch);
    }
    if (!empty($completePatch)) {
        print_r($completePatch);
    }
    if (!empty($partialPatch)) {
        print_r($partialPatch);
    }
    echo '
'."\n"; if (!empty($update)) { echo '

Update Object

'."\n"; echo '
'."\n";
        print_r($update);
        echo '
'."\n"; } echo ''."\n"; echo ''; exit; } // Set header and send info. $memcache->set($rawPath,$xml); $xml->printXml(); exit; ?>