/**
  * Parses a stream containing info from a packages_update.xml.
  *
  * @param	string		$content
  * @return	array		$allNewPackages
  */
 protected static function parsePackageUpdateXML($content)
 {
     // load xml document
     $xml = new XML();
     $xml->loadXML('packageUpdateServer.xml', $content);
     $xpath = $xml->xpath();
     // loop through <package> tags inside the <section> tag.
     $allNewPackages = array();
     $packages = $xpath->query('/ns:section[@name=\'packages\']/ns:package');
     foreach ($packages as $package) {
         if (!Package::isValidPackageName($package->getAttribute('name'))) {
             throw new SystemException("'" . $package->getAttribute('name') . "' is not a valid package name.");
         }
         $allNewPackages[$package->getAttribute('name')] = self::parsePackageUpdateXMLBlock($xpath, $package);
     }
     return $allNewPackages;
 }
 /**
  * Uninstalls the specified package.
  * $package may either be the packageID or the package identifier.
  * 
  * @param	mixed	$package
  */
 private function uninstall($package)
 {
     if (Package::isValidPackageName($package)) {
         $packageID = PackageCache::getInstance()->getPackageID($package);
     } else {
         $packageID = $package;
     }
     // UninstallPackageAction::prepare()
     $package = new Package($packageID);
     if (!$package->packageID || !$package->canUninstall()) {
         $this->error('invalidUninstallation');
     }
     // get new process no
     $processNo = PackageInstallationQueue::getNewProcessNo();
     // create queue
     $queue = PackageInstallationQueueEditor::create(array('processNo' => $processNo, 'userID' => CLIWCF::getUser()->userID, 'packageName' => $package->getName(), 'packageID' => $package->packageID, 'action' => 'uninstall'));
     // initialize uninstallation
     $installation = new PackageUninstallationDispatcher($queue);
     $installation->nodeBuilder->purgeNodes();
     $installation->nodeBuilder->buildNodes();
     CLIWCF::getTPL()->assign(array('queue' => $queue));
     $queueID = $installation->nodeBuilder->getQueueByNode($queue->processNo, $installation->nodeBuilder->getNextNode());
     $step = 'uninstall';
     $node = $installation->nodeBuilder->getNextNode();
     $currentAction = CLIWCF::getLanguage()->get('wcf.package.installation.step.uninstalling');
     $progress = 0;
     // initialize progressbar
     $progressbar = new ProgressBar(new ConsoleProgressBar(array('width' => CLIWCF::getTerminal()->getWidth(), 'elements' => array(ConsoleProgressBar::ELEMENT_PERCENT, ConsoleProgressBar::ELEMENT_BAR, ConsoleProgressBar::ELEMENT_TEXT), 'textWidth' => min(floor(CLIWCF::getTerminal()->getWidth() / 2), 50))));
     // InstallPackageAction::readParameters()
     $finished = false;
     while (!$finished) {
         $queue = new PackageInstallationQueue($queueID);
         $installation = new PackageUninstallationDispatcher($queue);
         switch ($step) {
             case 'uninstall':
                 $_node = $installation->uninstall($node);
                 if ($_node == '') {
                     // remove node data
                     $installation->nodeBuilder->purgeNodes();
                     // UninstallPackageAction::finalize()
                     CacheHandler::getInstance()->flushAll();
                     // /UninstallPackageAction::finalize()
                     // show success
                     $currentAction = CLIWCF::getLanguage()->get('wcf.acp.package.uninstallation.step.success');
                     $progress = 100;
                     $step = 'success';
                     $finished = true;
                     continue;
                 }
                 // continue with next node
                 $queueID = $installation->nodeBuilder->getQueueByNode($installation->queue->processNo, $installation->nodeBuilder->getNextNode($node));
                 $step = 'uninstall';
                 $progress = $installation->nodeBuilder->calculateProgress($node);
                 $node = $_node;
         }
         $progressbar->update($progress, $currentAction);
     }
     $progressbar->getAdapter()->finish();
 }
Example #3
0
 /**
  * Registers a deferred message. Returns `true` on any well-formed message and `false`
  * otherwise.
  * Deferred messages will be sent on shutdown. This can be useful if your handler depends
  * on data that may not be written to database yet or to achieve a better performance as the
  * page is delivered first.
  * 
  * ATTENTION: Use this method only if your messages are not critical as you cannot check
  * whether your message was delivered successfully.
  * ATTENTION: Do NOT (!) send any security related information via sendDeferredMessage.
  * Not every push service can validate whether the userID given was forged by a malicious client!
  * 
  * @see	\wcf\system\push\PushHandler::sendMessage()
  */
 public function sendDeferredMessage($message, array $userIDs = array(), array $payload = array())
 {
     if (!$this->isEnabled()) {
         return false;
     }
     if (!\wcf\data\package\Package::isValidPackageName($message)) {
         return false;
     }
     $userIDs = array_unique(\wcf\util\ArrayUtil::toIntegerArray($userIDs));
     $this->deferred[] = array('message' => $message, 'userIDs' => $userIDs, 'payload' => $payload);
     return true;
 }
 /**
  * Parses a stream containing info from a packages_update.xml.
  * 
  * @param	string		$content
  * @return	array		$allNewPackages
  */
 protected function parsePackageUpdateXML($content)
 {
     // load xml document
     $xml = new XML();
     $xml->loadXML('packageUpdateServer.xml', $content);
     $xpath = $xml->xpath();
     $allNewPackages = array();
     $packages = $xpath->query('/ns:section/ns:package');
     foreach ($packages as $package) {
         if (!Package::isValidPackageName($package->getAttribute('name'))) {
             throw new SystemException("'" . $package->getAttribute('name') . "' is not a valid package name.");
         }
         $allNewPackages[$package->getAttribute('name')] = $this->parsePackageUpdateXMLBlock($xpath, $package);
     }
     return $allNewPackages;
 }
Example #5
0
	/**
	 * @see	wcf\form\IForm::validate()
	 */
	public function validate() {
		parent::validate();
		
		if ($this->exportAsPackage) {
			if (empty($this->packageName)) {
				throw new UserInputException('packageName');
			}
			
			if (!Package::isValidPackageName($this->packageName)) {
				throw new UserInputException('packageName', 'notValid');
			}
			
			// 3rd party packages may never have com.woltlab.* as name
			if (strpos($this->packageName, 'com.woltlab.') === 0) {
				throw new UserInputException('packageName', 'reserved');
			}
		}
	}
Example #6
0
	/**
	 * Extracts information about this package (parses package.xml).
	 */
	protected function readPackageInfo() {
		// search package.xml in package archive
		// throw error message if not found
		if ($this->tar->getIndexByFilename(self::INFO_FILE) === false) {
			throw new SystemException("package information file '".(self::INFO_FILE)."' not found in '".$this->archive."'");
		}
		
		// extract package.xml, parse with SimpleXML
		// and compile an array with XML::getElementTree()
		$xml = new XML();
		try {
			$xml->loadXML(self::INFO_FILE, $this->tar->extractToString(self::INFO_FILE));
		}
		catch (\Exception $e) { // bugfix to avoid file caching problems
			$xml->loadXML(self::INFO_FILE, $this->tar->extractToString(self::INFO_FILE));
		}
		
		// parse xml
		$xpath = $xml->xpath();
		$package = $xpath->query('/ns:package')->item(0);
		
		// package name
		$packageName = $package->getAttribute('name');
		if (!Package::isValidPackageName($packageName)) {
			// package name is not a valid package identifier
			throw new SystemException("'".$packageName."' is not a valid package name.");
		}
		
		$this->packageInfo['name'] = $packageName;
		
		// get package information
		$packageInformation = $xpath->query('./ns:packageinformation', $package)->item(0);
		$elements = $xpath->query('child::*', $packageInformation);
		foreach ($elements as $element) {
			switch ($element->tagName) {
				case 'packagename':
				case 'packagedescription':
				case 'readme':
				case 'license':
					if (!isset($this->packageInfo[$element->tagName])) $this->packageInfo[$element->tagName] = array();
					
					$languageCode = 'default';
					if ($element->hasAttribute('language')) {
						$languageCode = $element->getAttribute('language');
					}
					
					// fix case-sensitive names
					$name = $element->tagName;
					if ($name == 'packagename') $name = 'packageName';
					else if ($name == 'packagedescription') $name = 'packageDescription';
					
					$this->packageInfo[$name][$languageCode] = $element->nodeValue;
				break;
				
				case 'isapplication':
					$this->packageInfo['isApplication'] = intval($element->nodeValue);
				break;
				
				case 'packageurl':
					$this->packageInfo['packageURL'] = $element->nodeValue;
				break;
				
				case 'version':
					if (!Package::isValidVersion($element->nodeValue)) {
						throw new SystemException("package version '".$element->nodeValue."' is invalid");
					}
					
					$this->packageInfo['version'] = $element->nodeValue;
				break;
				
				case 'date':
					DateUtil::validateDate($element->nodeValue);
					
					$this->packageInfo['date'] = strtotime($element->nodeValue);
				break;
			}
		}
		
		// get author information
		$authorInformation = $xpath->query('./ns:authorinformation', $package)->item(0);
		$elements = $xpath->query('child::*', $authorInformation);
		foreach ($elements as $element) {
			$tagName = ($element->tagName == 'authorurl') ? 'authorURL' : $element->tagName;
			$this->authorInfo[$tagName] = $element->nodeValue;
		}
		
		// get required packages
		$elements = $xpath->query('child::ns:requiredpackages/ns:requiredpackage', $package);
		foreach ($elements as $element) {
			if (!Package::isValidPackageName($element->nodeValue)) {
				throw new SystemException("'".$element->nodeValue."' is not a valid package name.");
			}
			
			// read attributes
			$data = array('name' => $element->nodeValue);
			$attributes = $xpath->query('attribute::*', $element);
			foreach ($attributes as $attribute) {
				$data[$attribute->name] = $attribute->value;
			}
					
			$this->requirements[$element->nodeValue] = $data;
		}
		
		// get optional packages
		$elements = $xpath->query('child::ns:optionalpackages/ns:optionalpackage', $package);
		foreach ($elements as $element) {
			if (!Package::isValidPackageName($element->nodeValue)) {
				throw new SystemException("'".$element->nodeValue."' is not a valid package name.");
			}
			
			// read attributes
			$data = array('name' => $element->nodeValue);
			$attributes = $xpath->query('attribute::*', $element);
			foreach ($attributes as $attribute) {
				$data[$attribute->name] = $attribute->value;
			}
					
			$this->optionals[] = $data;
		}
		
		// get excluded packages
		$elements = $xpath->query('child::ns:excludedpackages/ns:excludedpackage', $package);
		foreach ($elements as $element) {
			if (!Package::isValidPackageName($element->nodeValue)) {
				throw new SystemException("'".$element->nodeValue."' is not a valid package name.");
			}
			
			// read attributes
			$data = array('name' => $element->nodeValue);
			$attributes = $xpath->query('attribute::*', $element);
			foreach ($attributes as $attribute) {
				$data[$attribute->name] = $attribute->value;
			}
			
			$this->excludedPackages[] = $data;
		}
		
		// get instructions
		$elements = $xpath->query('./ns:instructions', $package);
		foreach ($elements as $element) {
			$instructionData = array();
			$instructions = $xpath->query('./ns:instruction', $element);
			foreach ($instructions as $instruction) {
				$data = array();
				$attributes = $xpath->query('attribute::*', $instruction);
				foreach ($attributes as $attribute) {
					$data[$attribute->name] = $attribute->value;
				}
				
				$instructionData[] = array(
					'attributes' => $data,
					'pip' => $instruction->getAttribute('type'),
					'value' => $instruction->nodeValue
				);
			}
			
			$fromVersion = $element->getAttribute('fromversion');
			$type = $element->getAttribute('type');
			
			if ($type == 'install') {
				$this->instructions['install'] = $instructionData;
			}
			else {
				$this->instructions['update'][$fromVersion] = $instructionData;
			}
		}
		
		// get php requirements
		$requirements = $xpath->query('./ns:phprequirements', $package);
		foreach ($requirements as $requirement) {
			$elements = $xpath->query('child::*', $requirement);
			foreach ($elements as $element) {
				switch ($element->tagName) {
					case 'version':
						$this->phpRequirements['version'] = $element->nodeValue;
					break;
					
					case 'setting':
						$this->phpRequirements['settings'][$element->getAttribute('name')] = $element->nodeValue;
					break;
					
					case 'extension':
						$this->phpRequirements['extensions'][] = $element->nodeValue;
					break;
					
					case 'function':
						$this->phpRequirements['functions'][] = $element->nodeValue;
					break;
					
					case 'class':
						$this->phpRequirements['classes'][] = $element->nodeValue;
					break;
				}
			}
		}
		
		// add com.woltlab.wcf to package requirements
		if (!isset($this->requirements['com.woltlab.wcf']) && $this->packageInfo['name'] != 'com.woltlab.wcf') {
			$this->requirements['com.woltlab.wcf'] = array('name' => 'com.woltlab.wcf');
		}
		
		if ($this->package != null) {
			$validFromVersion = null;
			foreach ($this->instructions['update'] as $fromVersion => $update) {
				if (Package::checkFromversion($this->package->packageVersion, $fromVersion)) {
					$validFromVersion = $fromVersion;
					break;
				}
			}
			if ($validFromVersion === null) {
				$this->instructions['update'] = array();
			}
			else {
				$this->instructions['update'] = $this->instructions['update'][$validFromVersion];
			}
		}
		
		// set default values
		if (!isset($this->packageInfo['isApplication'])) $this->packageInfo['isApplication'] = 0;
		if (!isset($this->packageInfo['packageURL'])) $this->packageInfo['packageURL'] = '';
	}