set('addons', $this->Amo->addonTypes); }*/ /** * Add new or new version of an add-on * @param int $id */ function add($id = '') { $this->layout = 'developers'; $this->set('addonTypes', $this->Amo->addonTypes); //Determine if an adding a new addon or new version if ($id != '' && $this->Amo->checkOwnership($id)) { $this->Addon->id = $id; $existing = $this->Addon->read(); $this->set('existing', $existing); $newAddon = false; } else { $newAddon = true; } $this->set('id', $id); $this->set('newAddon', $newAddon); //Step 2: Parse uploaded file and if correct, display addon-wide information form if (isset($this->data['Addon']['add_step1'])) { //Check for model validation first (in step 1, this is just addon type) if (!$this->Addon->validates($this->data)) { $this->validateErrors(); $this->set('fileError', ''); $this->render('add_step1'); die(); } //Check for file upload errors if ($this->data['Addon']['file']['error'] !== 0) { $this->Addon->invalidate('file'); $fileErrors = array('1' => _('Exceeds maximum upload size'), '2' => _('Exceeds maximum upload size'), '3' => _('Incomplete transfer'), '4' => _('No file uploaded') ); $fileError = $fileErrors[$this->data['Addon']['file']['error']]; $this->set('fileError', $fileError); $this->render('add_step1'); die(); } $fileName = $this->data['Addon']['file']['name']; $fileSize = round($this->data['Addon']['file']['size']/1024, 1); //in KB $fileExtension = substr($fileName, strrpos($fileName, '.')); $allowedExtensions = array('.xpi', '.jar', '.src'); //Check for file extenion match if (!in_array($fileExtension, $allowedExtensions)) { $this->Addon->invalidate('file'); $this->set('fileError', sprintf(_('Disallowed file extension (%s)'), $fileExtension)); $this->render('add_step1'); die(); } //Move temporary file to repository $uploadedFile = $this->data['Addon']['file']['tmp_name']; $tempLocation = REPO_PATH.'/temp/'.$fileName; if (move_uploaded_file($uploadedFile, $tempLocation)) { $uploadedFile = $tempLocation; chmod($uploadedFile, 0644); } else { $this->Addon->invalidate('file'); $this->set('fileError', _('Could not move file')); $this->render('add_step1'); die(); } //Search plugins do not have install.rdf to parse if ($this->Amo->addonTypes[$this->data['Addon']['addontype_id']] != 'Search Plugin') { //Extract install.rdf from the package $zip = new Archive_Zip($uploadedFile); $extraction = $zip->extract(array('extract_as_string' => true, 'by_name' => array('install.rdf'))); //Make sure install.rdf is present if ($extraction !== 0) { $fileContents = $extraction[0]['content']; } else { $this->Addon->invalidate('file'); $this->set('fileError', _('No install.rdf present')); $this->render('add_step1'); die(); } //Use Rdf Component to parse install.rdf $manifestData = $this->Rdf->parseInstallManifest($fileContents); //If the result is a string, it is an error message if (!is_array($manifestData)) { $this->Addon->invalidate('file'); $this->set('fileError', sprintf(_('The following error occurred while parsing install.rdf: %s'), $manifestData)); $this->render('add_step1'); die(); } //Check if install.rdf has an updateURL if (isset($manifestData['updateURL'])) { $this->Addon->invalidate('file'); $this->set('fileError', _('Add-ons cannot use an external updateURL. Please remove this from install.rdf and try again.')); $this->render('add_step1'); die(); } //Check the GUID if (!isset($manifestData['id']) || !preg_match('/^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i', $manifestData['id'])) { $this->Addon->invalidate('file'); $this->set('fileError', _('The ID of this add-on is invalid or not set.')); $this->render('add_step1'); die(); } //Make sure version has no spaces if (!isset($manifestData['version']) || preg_match('/.*\s.*/', $manifestData['version'])) { $this->Addon->invalidate('file'); $this->set('fileError', _('The version of this add-on is invalid or not set. Versions cannot contain spaces.')); $this->render('add_step1'); die(); } //These are arrays by locale $addonNames = $manifestData['name']; $addonDesc = $manifestData['description']; //In case user said it was a new add-on when it is actually an update if ($existing = $this->Addon->findAllByGuid($manifestData['id'])) { if ($newAddon === true) { $newAddon = false; $this->set('newAddon', $newAddon); } $existing = $existing[0]; } else { if ($newAddon === false) { $newAddon = true; $this->set('newAddon', $newAddon); } } //Initialize targetApp checking $noMozApps = true; $versionErrors = array(); if (count($manifestData['targetApplication']) > 0) { //Iterate through each target app and find it in the DB foreach ($manifestData['targetApplication'] as $appKey => $appVal) { if ($matchingApp = $this->Application->find(array('guid' => $appKey), null, null, -1)) { $noMozApps = false; //Check if the minVersion is valid if (!$matchingMinVers = $this->Appversion->find(array( 'application_id' => $matchingApp['Application']['id'], 'version' => $appVal['minVersion'], 'public' => 1 ), null, null, -1)) { $versionErrors[] = sprintf(_('%s is not a valid version for %s'), $appVal['minVersion'], $matchingApp['Application']['name']); } //Check if the maxVersion is valid if (!$matchingMaxVers = $this->Appversion->find(array( 'application_id' => $matchingApp['Application']['id'], 'version' => $appVal['maxVersion'], 'public' => 1 ), null, null, -1)) { $versionErrors[] = sprintf(_('%s is not a valid version for %s'), $appVal['maxVersion'], $matchingApp['Application']['name']); } } } } //Must have at least one mozilla app if ($noMozApps === true) { $this->Addon->invalidate('file'); $this->set('fileError', _('You must have at least one valid Mozilla Target Application.')); $this->render('add_step1'); die(); } //Max/min version errors if (count($versionErrors) > 0) { $this->Addon->invalidate('file'); $errorStr = implode($versionErrors, '
'); $this->set('fileError', _('The following errors were found in install.rdf:').'
'.$errorStr); $this->render('add_step1'); die(); } } //If it is a search plugin, read the .src file else { } $info['name'] = (!empty($existing['Addon']['name'])) ? $existing['Addon']['name'] : $manifestData['name']['en-US']; $info['description'] = (!empty($existing['Addon']['description'])) ? $existing['Addon']['description'] : $manifestData['description']['en-US']; $info['homepage'] = (!empty($existing['Addon']['homepage'])) ? $existing['Addon']['homepage'] : $manifestData['homepageURL']; $info['addontype_id'] = (!empty($existing['Addon']['addontype_id'])) ? $existing['Addon']['addontype_id'] : $this->data['Addon']['addontype_id']; $info['version'] = $manifestData['version']; $info['summary'] = $existing['Addon']['summary']; //Get tags based on addontype $tagsQry = $this->Tag->findAll(array('addontype_id' => $info['addontype_id']), null, null, null, null, -1); foreach ($tagsQry as $k => $v) { $tags[$v['Tag']['id']] = $v['Tag']['name']; } if (count($existing['Tag']) > 0) { foreach ($existing['Tag'] as $tag) { $info['selectedTags'][$tag['id']] = $tag['name']; } } else { $info['selectedTags'] = array(); } $this->set('tags', $tags); $this->set('info', $info); $this->set('fileName', $fileName); $this->set('fileSize', $fileSize); $this->set('manifestData', $manifestData); $this->render('add_step2'); } elseif (isset($this->data['Addon']['add_step2']) || isset($this->data['Addon']['add_step25'])) { //Step 2 processing if (isset($this->data['Addon']['add_step2'])) { //Check for model validation first if (!$this->Addon->validates($this->data)) { $this->validateErrors(); $this->render('add_step2'); die(); } //Updated Addon if ($newAddon === false) { //Check for identical versions if ($this->Version->findAll()) { $this->invalidate('general'); $this->set('generalError', sprintf(_('An identical version (%s) already exists for this add-on and platform.'), $this->data['Addon']['version'])); $this->render('add_step2'); die(); } //Update addon //Delete current authors //Add new authors //Delete old tags //Add new tags } //New Addon else { //Check for duplicate names if ($this->Addon->findAllByName($this->data['Addon']['name'])) { $this->invalidate('general'); $this->set('generalError', _('The name for your add-on already exists in the database. Please make sure that:
  • Your GUIDs match. The most common cause for this error is mismatched GUIDs.
  • You do not have a duplicate entry in the database. If you do, you should update that entry or delete it and try again.
  • ')); $this->render('add_step2'); die(); } //Insert addon //Add authors //Add tags } if($this->data['Addon']['ShowEula'] == 1) { $this->render('add_step25'); die(); } //Else, continue and show step3 } //Step 2.5 processing if (isset($this->data['Addon']['add_step25'])) { //Update EULA/PP } //Get Platforms list $platformQry = $this->Platform->findAll(); foreach ($platformQry as $k => $v) { $platforms[$v['Platform']['id']] = $v['Platform']['name']; } $this->set('platforms', $platforms); $this->render('add_step3'); } elseif (isset($this->data['Addon']['add_step3'])) { //Check for model validation first if (!$this->Version->validates($this->data)) { $this->validateErrors(); $this->render('add_step3'); die(); } //Construct new filename //Move file //Insert version //Insert files //Cancel any pending approvals (TODO warn earlier in process) //Approval queue $this->render('add_step4'); } //Step 1: Add-on type and file upload else { $this->set('fileError', ''); $this->render('add_step1'); } } /** * Manage an add-on * @param int $id */ function manage($id) { } /** * Edit add-on * @param int $id * function edit($id) { }*/ /** * Edit a version * @param int $id */ function editVersion($id) { } /** * AJAX action for looking up an author by email * @param string $email */ function authorLookup($email) { if ($authors = $this->User->findAllByEmail($email)) { $author = $authors[0]['User']['firstname'].' '.$authors[0]['User']['lastname']; $author .= ' ['.$authors[0]['User']['email'].']'; } else { $author = false; } $this->set('author', $author); $this->set('email', $email); $this->render('author_lookup', 'ajax'); } } ?>