Beispiel #1
0
	/**
	 * New node is found.
	 * @return bool
	 */
	public function nodeOpened(NMacroNode $node)
	{
		$this->used = TRUE;
		$node->isEmpty = FALSE;
		$node->openingCode = NPhpWriter::using($node)
			->write('<?php if (NCacheMacro::createCache($netteCacheStorage, %var, $_g->caches, %node.array?)) { ?>',
				NStrings::random()
			);
	}
Beispiel #2
0
	/**
	 * Process all {macros} and <tags/>.
	 * @param  string
	 * @return string
	 */
	public function parse($s)
	{
		if (!NStrings::checkEncoding($s)) {
			throw new NLatteException('Template is not valid UTF-8 stream.');
		}
		$s = str_replace("\r\n", "\n", $s);

		$this->templateId = NStrings::random();
		$this->input = & $s;
		$this->offset = 0;
		$this->output = '';
		$this->htmlNodes = $this->macroNodes = array();

		foreach ($this->macroHandlers as $handler) {
			$handler->initialize($this);
		}

		$len = strlen($s);

		try {
			while ($this->offset < $len) {
				$matches = $this->{"context".$this->context[0]}();

				if (!$matches) { // EOF
					break;

				} elseif (!empty($matches['comment'])) { // {* *}

				} elseif (!empty($matches['macro'])) { // {macro}
					list($macroName, $macroArgs, $macroModifiers) = $this->parseMacro($matches['macro']);
					$isRightmost = $this->offset >= $len || $this->input[$this->offset] === "\n";
					$this->writeMacro($macroName, $macroArgs, $macroModifiers, $isRightmost);

				} else { // common behaviour
					$this->output .= $matches[0];
				}
			}
		} catch (NLatteException $e) {
			if (!$e->sourceLine) {
				$e->sourceLine = $this->getLine();
			}
			throw $e;
		}

		$this->output .= substr($this->input, $this->offset);

		foreach ($this->htmlNodes as $node) {
			if (!empty($node->attrs)) {
				throw new NLatteException("Missing end tag </$node->name> for macro-attribute " . self::N_PREFIX
					. implode(' and ' . self::N_PREFIX, array_keys($node->attrs)) . ".", 0, $this->getLine());
			}
		}

		$prologs = $epilogs = '';
		foreach ($this->macroHandlers as $handler) {
			$res = $handler->finalize();
			$handlerName = get_class($handler);
			$prologs .= empty($res[0]) ? '' : "<?php\n// prolog $handlerName\n$res[0]\n?>";
			$epilogs = (empty($res[1]) ? '' : "<?php\n// epilog $handlerName\n$res[1]\n?>") . $epilogs;
		}
		$this->output = ($prologs ? $prologs . "<?php\n//\n// main template\n//\n?>\n" : '') . $this->output . $epilogs;

		if ($this->macroNodes) {
			throw new NLatteException("There are unclosed macros.", 0, $this->getLine());
		}

		return $this->output;
	}
Beispiel #3
0
	/**
	 * @return void
	 */
	public function __destruct()
	{
		if (self::$fixIE && isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE ') !== FALSE
			&& in_array($this->code, array(400, 403, 404, 405, 406, 408, 409, 410, 500, 501, 505), TRUE)
			&& $this->getHeader('Content-Type', 'text/html') === 'text/html'
		) {
			echo NStrings::random(2e3, " \t\r\n"); // sends invisible garbage for IE
			self::$fixIE = FALSE;
		}
	}
Beispiel #4
0
	/**
	 * Returns session namespace provided to pass temporary data between redirects.
	 * @return NSessionSection
	 */
	public function getFlashSession()
	{
		if (empty($this->params[self::FLASH_KEY])) {
			$this->params[self::FLASH_KEY] = NStrings::random(4);
		}
		return $this->getSession('Nette.Application.Flash/' . $this->params[self::FLASH_KEY]);
	}
Beispiel #5
0
	/**
	 * Returns encoded message.
	 * @return string
	 */
	public function generateMessage()
	{
		$output = '';
		$boundary = '--------' . NStrings::random();

		foreach ($this->headers as $name => $value) {
			$output .= $name . ': ' . $this->getEncodedHeader($name);
			if ($this->parts && $name === 'Content-Type') {
				$output .= ';' . self::EOL . "\tboundary=\"$boundary\"";
			}
			$output .= self::EOL;
		}
		$output .= self::EOL;

		$body = (string) $this->body;
		if ($body !== '') {
			switch ($this->getEncoding()) {
			case self::ENCODING_QUOTED_PRINTABLE:
				$output .= function_exists('quoted_printable_encode') ? quoted_printable_encode($body) : self::encodeQuotedPrintable($body);
				break;

			case self::ENCODING_BASE64:
				$output .= rtrim(chunk_split(base64_encode($body), self::LINE_LENGTH, self::EOL));
				break;

			case self::ENCODING_7BIT:
				$body = preg_replace('#[\x80-\xFF]+#', '', $body);
				// break intentionally omitted

			case self::ENCODING_8BIT:
				$body = str_replace(array("\x00", "\r"), '', $body);
				$body = str_replace("\n", self::EOL, $body);
				$output .= $body;
				break;

			default:
				throw new InvalidStateException('Unknown encoding.');
			}
		}

		if ($this->parts) {
			if (substr($output, -strlen(self::EOL)) !== self::EOL) {
				$output .= self::EOL;
			}
			foreach ($this->parts as $part) {
				$output .= '--' . $boundary . self::EOL . $part->generateMessage() . self::EOL;
			}
			$output .= '--' . $boundary.'--';
		}

		return $output;
	}
Beispiel #6
0
	/**
	 * Cross-Site Request Forgery (CSRF) form protection.
	 * @param  string
	 * @param  int
	 * @return void
	 */
	public function addProtection($message = NULL, $timeout = NULL)
	{
		$session = $this->getSession()->getSection('Nette.Forms.Form/CSRF');
		$key = "key$timeout";
		if (isset($session->$key)) {
			$token = $session->$key;
		} else {
			$session->$key = $token = NStrings::random();
		}
		$session->setExpiration($timeout, $key);
		$this[self::PROTECTOR_ID] = new NHiddenField($token);
		$this[self::PROTECTOR_ID]->addRule(self::PROTECTION, $message, $token);
	}
Beispiel #7
0
	/**
	 * Starts and initializes session data.
	 * @throws InvalidStateException
	 * @return void
	 */
	public function start()
	{
		if (self::$started) {
			return;
		}

		$this->configure($this->options);

		NDebugger::tryError();
		session_start();
		if (NDebugger::catchError($e)) {
			@session_write_close(); // this is needed
			throw new InvalidStateException('session_start(): ' . $e->getMessage(), 0, $e);
		}

		self::$started = TRUE;

		/* structure:
			__NF: Counter, BrowserKey, Data, Meta, Time
				DATA: section->variable = data
				META: section->variable = Timestamp, Browser, Version
		*/

		unset($_SESSION['__NT'], $_SESSION['__NS'], $_SESSION['__NM']); // old unused structures

		// initialize structures
		$nf = & $_SESSION['__NF'];
		if (empty($nf)) { // new session
			$nf = array('C' => 0);
		} else {
			$nf['C']++;
		}

		// session regenerate every 30 minutes
		$nfTime = & $nf['Time'];
		$time = time();
		if ($time - $nfTime > self::REGENERATE_INTERVAL) {
			$nfTime = $time;
			$this->regenerationNeeded = TRUE;
		}

		// browser closing detection
		$browserKey = $this->request->getCookie('nette-browser');
		if (!$browserKey) {
			$browserKey = NStrings::random();
		}
		$browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey;
		$nf['B'] = $browserKey;

		// resend cookie
		$this->sendCookie();

		// process meta metadata
		if (isset($nf['META'])) {
			$now = time();
			// expire section variables
			foreach ($nf['META'] as $section => $metadata) {
				if (is_array($metadata)) {
					foreach ($metadata as $variable => $value) {
						if ((!empty($value['B']) && $browserClosed) || (!empty($value['T']) && $now > $value['T']) // whenBrowserIsClosed || Time
							|| ($variable !== '' && is_object($nf['DATA'][$section][$variable]) && (isset($value['V']) ? $value['V'] : NULL) // Version
								!== NClassReflection::from($nf['DATA'][$section][$variable])->getAnnotation('serializationVersion'))
						) {
							if ($variable === '') { // expire whole section
								unset($nf['META'][$section], $nf['DATA'][$section]);
								continue 2;
							}
							unset($nf['META'][$section][$variable], $nf['DATA'][$section][$variable]);
						}
					}
				}
			}
		}

		if ($this->regenerationNeeded) {
			session_regenerate_id(TRUE);
			$this->regenerationNeeded = FALSE;
		}

		register_shutdown_function(array($this, 'clean'));
	}
Beispiel #8
0
	/**
	 * Stores current request to session.
	 * @param  mixed  optional expiration time
	 * @return string key
	 */
	public function storeRequest($expiration = '+ 10 minutes')
	{
		$session = $this->session->getSection('Nette.Application/requests');
		do {
			$key = NStrings::random(5);
		} while (isset($session[$key]));

		$session[$key] = end($this->requests);
		$session->setExpiration($expiration, $key);
		return $key;
	}
Beispiel #9
0
	/**
	 * Starts and initializes session data.
	 * @throws InvalidStateException
	 * @return void
	 */
	public function start()
	{
		if (self::$started) {
			return;
		}

		$this->configure($this->options);

		$id = & $_COOKIE[session_name()];
		if (!is_string($id) || !preg_match('#^[0-9a-zA-Z,-]{22,128}\z#i', $id)) {
			unset($_COOKIE[session_name()]);
		}

		set_error_handler(create_function('$severity, $message', 'extract($GLOBALS[0]['.array_push($GLOBALS[0], array('error'=>& $error)).'-1], EXTR_REFS); // session_start returns FALSE on failure since PHP 5.3.0.
			if (($severity & error_reporting()) === $severity) {
				$error = $message;
				restore_error_handler();
			}
		'));
		session_start();
		if (!$error) {
			restore_error_handler();
		}
		$this->response->removeDuplicateCookies();
		if ($error && !session_id()) {
			@session_write_close(); // this is needed
			throw new InvalidStateException("session_start(): $error");
		}

		self::$started = TRUE;

		/* structure:
			__NF: Counter, BrowserKey, Data, Meta, Time
				DATA: section->variable = data
				META: section->variable = Timestamp, Browser, Version
		*/

		unset($_SESSION['__NT'], $_SESSION['__NS'], $_SESSION['__NM']); // old unused structures

		// initialize structures
		$nf = & $_SESSION['__NF'];
		@$nf['C']++;

		// regenerate empty session
		if (empty($nf['Time'])) {
			$nf['Time'] = time();
			$this->regenerated = TRUE;
		}

		// browser closing detection
		$browserKey = $this->request->getCookie('nette-browser');
		if (!$browserKey) {
			$browserKey = NStrings::random();
		}
		$browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey;
		$nf['B'] = $browserKey;

		// resend cookie
		$this->sendCookie();

		// process meta metadata
		if (isset($nf['META'])) {
			$now = time();
			// expire section variables
			foreach ($nf['META'] as $section => $metadata) {
				if (is_array($metadata)) {
					foreach ($metadata as $variable => $value) {
						if ((!empty($value['B']) && $browserClosed) || (!empty($value['T']) && $now > $value['T']) // whenBrowserIsClosed || Time
							|| (isset($nf['DATA'][$section][$variable]) && is_object($nf['DATA'][$section][$variable]) && (isset($value['V']) ? $value['V'] : NULL) // Version
								!= NClassReflection::from($nf['DATA'][$section][$variable])->getAnnotation('serializationVersion')) // intentionally !=
						) {
							if ($variable === '') { // expire whole section
								unset($nf['META'][$section], $nf['DATA'][$section]);
								continue 2;
							}
							unset($nf['META'][$section][$variable], $nf['DATA'][$section][$variable]);
						}
					}
				}
			}
		}

		if ($this->regenerated) {
			$this->regenerated = FALSE;
			$this->regenerateId();
		}

		register_shutdown_function(array($this, 'clean'));
	}
Beispiel #10
0
	/**
	 * Generates code for macro <tag n:attr> to the output.
	 * @param  string
	 * @return void
	 */
	public function writeAttrsMacro($code, NHtmlNode $htmlNode)
	{
		$attrs = $htmlNode->macroAttrs;
		$left = $right = array();
		$attrCode = '';

		foreach ($this->macros as $name => $foo) {
			$attrName = NMacroNode::PREFIX_INNER . "-$name";
			if (isset($attrs[$attrName])) {
				if ($htmlNode->closing) {
					$left[] = array("/$name", '', NMacroNode::PREFIX_INNER);
				} else {
					array_unshift($right, array($name, $attrs[$attrName], NMacroNode::PREFIX_INNER));
				}
				unset($attrs[$attrName]);
			}
		}

		foreach (array_reverse($this->macros) as $name => $foo) {
			$attrName = NMacroNode::PREFIX_TAG . "-$name";
			if (isset($attrs[$attrName])) {
				$left[] = array($name, $attrs[$attrName], NMacroNode::PREFIX_TAG);
				array_unshift($right, array("/$name", '', NMacroNode::PREFIX_TAG));
				unset($attrs[$attrName]);
			}
		}

		foreach ($this->macros as $name => $foo) {
			if (isset($attrs[$name])) {
				if ($htmlNode->closing) {
					$right[] = array("/$name", '', NULL);
				} else {
					array_unshift($left, array($name, $attrs[$name], NULL));
				}
				unset($attrs[$name]);
			}
		}

		if ($attrs) {
			throw new NCompileException("Unknown macro-attribute " . NParser::N_PREFIX
				. implode(' and ' . NParser::N_PREFIX, array_keys($attrs)));
		}

		if (!$htmlNode->closing) {
			$htmlNode->attrCode = & $this->attrCodes[$uniq = ' n:' . NStrings::random()];
			$code = substr_replace($code, $uniq, ($tmp=strrpos($code, '/>')) ? $tmp : strrpos($code, '>'), 0);
		}

		foreach ($left as $item) {
			$node = $this->writeMacro($item[0], $item[1], NULL, NULL, $htmlNode, $item[2]);
			if ($node->closing || $node->isEmpty) {
				$htmlNode->attrCode .= $node->attrCode;
				if ($node->isEmpty) {
					unset($htmlNode->macroAttrs[$node->name]);
				}
			}
		}

		$this->output .= $code;

		foreach ($right as $item) {
			$node = $this->writeMacro($item[0], $item[1], NULL, NULL, $htmlNode);
			if ($node->closing) {
				$htmlNode->attrCode .= $node->attrCode;
			}
		}

		if ($right && substr($this->output, -2) === '?>') {
			$this->output .= "\n";
		}
	}
Beispiel #11
0
	/** @return string */
	private function getRandomId()
	{
		return '<' . NStrings::random() . '@' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
			: (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost'))
			. '>';
	}