Exemplo n.º 1
0
 /**
  * Static factory.
  * @param  string element name (or NULL)
  * @param  array|string element's attributes or plain text content
  * @return self
  */
 public static function el($name = NULL, $attrs = NULL)
 {
     $el = new static();
     $parts = explode(' ', $name, 2);
     $el->setName($parts[0]);
     if (is_array($attrs)) {
         $el->attrs = $attrs;
     } elseif ($attrs !== NULL) {
         $el->setText($attrs);
     }
     if (isset($parts[1])) {
         foreach (Strings::matchAll($parts[1] . ' ', '#([a-z0-9:-]+)(?:=(["\'])?(.*?)(?(2)\\2|\\s))?#i') as $m) {
             $el->attrs[$m[1]] = isset($m[3]) ? $m[3] : TRUE;
         }
     }
     return $el;
 }
 /**
  * Parse search query.
  *
  * @param  string
  * @return array associative array with keys 'query' and 'tags'
  */
 public function parseQuery($input)
 {
     // normalize input
     $input = Strings::lower(Strings::trim($input));
     $input = Strings::replace($input, '/\\s+/', ' ');
     // extract tags
     $matches = Strings::matchAll($input, '/(?<=^|\\s)tag:\\s*(?<tag_list>[\\pL\\d_-]+(?:\\s*,\\s*(?&tag_list))?)/u');
     $tags = array();
     $query = $input;
     foreach ($matches as $m) {
         $tmp = Strings::split($m['tag_list'], '/\\s*,\\s*/');
         $tmp = array_map('Nette\\Utils\\Strings::webalize', $tmp);
         $tmp = array_unique($tmp);
         $tags = array_merge($tags, $tmp);
         $query = str_replace($m[0], '', $query);
     }
     $query = Strings::trim($query) ?: null;
     return array('query' => $query, 'tags' => $tags);
 }
 public function proccessTweetForm($form, array $values)
 {
     $text = $values['tweet'];
     $matches = Strings::matchAll($text, '~#([a-z0-9-]++)~');
     $tags = array_column($matches, 1);
     $user = $this->users->getById($this->userId);
     $tweet = new Model\Tweet();
     $tweet->user = $user;
     $tweet->text = $values['tweet'];
     $existingTags = $this->tags->findBy(['name' => $tags])->fetchPairs('name');
     $newTags = array_diff($tags, array_keys($existingTags));
     foreach ($newTags as $tag) {
         $tweet->tags->add(new Model\Tag($tag));
     }
     foreach ($existingTags as $tag) {
         $tweet->tags->add($tag);
     }
     $this->tweets->persist($tweet);
     $this->tweets->flush();
     $this->redirect('this');
 }
Exemplo n.º 4
0
 /**
  * Tokenize string.
  * @param  string
  * @return array
  */
 public function tokenize($input)
 {
     $this->input = $input;
     if ($this->types) {
         $this->tokens = Strings::matchAll($input, $this->re);
         $len = 0;
         $count = count($this->types);
         $line = 1;
         foreach ($this->tokens as &$match) {
             $type = NULL;
             for ($i = 1; $i <= $count; $i++) {
                 if (!isset($match[$i])) {
                     break;
                 } elseif ($match[$i] != NULL) {
                     $type = $this->types[$i - 1];
                     break;
                 }
             }
             $match = self::createToken($match[0], $type, $line);
             $len += strlen($match['value']);
             $line += substr_count($match['value'], "\n");
         }
         if ($len !== strlen($input)) {
             $errorOffset = $len;
         }
     } else {
         $this->tokens = Strings::split($input, $this->re, PREG_SPLIT_NO_EMPTY);
         if ($this->tokens && !Strings::match(end($this->tokens), $this->re)) {
             $tmp = Strings::split($this->input, $this->re, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
             list(, $errorOffset) = end($tmp);
         }
     }
     if (isset($errorOffset)) {
         $line = $errorOffset ? substr_count($this->input, "\n", 0, $errorOffset) + 1 : 1;
         $col = $errorOffset - strrpos(substr($this->input, 0, $errorOffset), "\n") + 1;
         $token = str_replace("\n", '\\n', substr($input, $errorOffset, 10));
         throw new TokenizerException("Unexpected '{$token}' on line {$line}, column {$col}.");
     }
     return $this->tokens;
 }
Exemplo n.º 5
0
 /**
  * Sets HTML body.
  * @param  string
  * @param  mixed base-path or FALSE to disable parsing
  * @return MandrillMessage  provides a fluent interface
  */
 public function setHtmlBody($html, $basePath = NULL)
 {
     if ($html instanceof ITemplate) {
         //$html->mail = $this;
         if ($basePath === NULL && $html instanceof IFileTemplate) {
             $basePath = dirname($html->getFile());
         }
         $html = $html->__toString(TRUE);
     }
     if ($basePath !== FALSE) {
         $cids = array();
         $matches = Strings::matchAll($html, '#(src\\s*=\\s*|background\\s*=\\s*|url\\()(["\'])(?![a-z]+:|[/\\#])(.+?)\\2#i', PREG_OFFSET_CAPTURE);
         foreach (array_reverse($matches) as $m) {
             $file = rtrim($basePath, '/\\') . '/' . $m[3][0];
             if (!isset($cids[$file])) {
                 $cids[$file] = substr($this->addEmbeddedFile($file)->getHeader("Content-ID"), 1, -1);
             }
             $html = substr_replace($html, "{$m[1][0]}{$m[2][0]}cid:{$cids[$file]}{$m[2][0]}", $m[0][1], strlen($m[0][0]));
         }
     }
     $this->mandrillMessage['html'] = $html;
     return $this;
 }
Exemplo n.º 6
0
 /**
  * Tokenize string.
  * @param  string
  * @return array
  */
 public function tokenize($input)
 {
     if ($this->types) {
         $tokens = Strings::matchAll($input, $this->re);
         $len = 0;
         $count = count($this->types);
         foreach ($tokens as &$match) {
             $type = NULL;
             for ($i = 1; $i <= $count; $i++) {
                 if (!isset($match[$i])) {
                     break;
                 } elseif ($match[$i] != NULL) {
                     $type = $this->types[$i - 1];
                     break;
                 }
             }
             $match = array(self::VALUE => $match[0], self::OFFSET => $len, self::TYPE => $type);
             $len += strlen($match[self::VALUE]);
         }
         if ($len !== strlen($input)) {
             $errorOffset = $len;
         }
     } else {
         $tokens = Strings::split($input, $this->re, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
         $last = end($tokens);
         if ($tokens && !Strings::match($last[0], $this->re)) {
             $errorOffset = $last[1];
         }
     }
     if (isset($errorOffset)) {
         list($line, $col) = $this->getCoordinates($input, $errorOffset);
         $token = str_replace("\n", '\\n', substr($input, $errorOffset, 10));
         throw new TokenizerException("Unexpected '{$token}' on line {$line}, column {$col}.");
     }
     return $tokens;
 }
Exemplo n.º 7
0
 /**
  * @param Table $table
  */
 protected function analyseColumns(Table $table)
 {
     $tableName = $table->getName();
     // Analyse columns
     $columns = $this->driver->getColumns($tableName);
     foreach ($columns as $key => $col) {
         $column = new Column();
         $column->setName($col['name']);
         $column->setNullable($col['nullable']);
         $column->setType(Helpers::columnType($col['nativetype']));
         $column->setDefault($col['default']);
         $column->setOnUpdate(Strings::contains($col['vendor']['Extra'], 'on update'));
         // Analyse ENUM
         if ($col['nativetype'] === ColumnTypes::NATIVE_TYPE_ENUM) {
             $enum = Strings::matchAll($col['vendor']['Type'], ColumnTypes::NATIVE_REGEX_ENUM, PREG_PATTERN_ORDER);
             if ($enum) {
                 $column->setEnum($enum[1]);
                 $column->setType(ColumnTypes::TYPE_ENUM);
                 $column->setSubType(Helpers::columnType($col['nativetype']));
             }
         }
         $table->addColumn($column);
     }
 }
Exemplo n.º 8
0
 /**
  * Sets HTML body.
  * @param  string
  * @param  mixed base-path
  * @return self
  */
 public function setHtmlBody($html, $basePath = NULL)
 {
     if ($basePath === NULL && ($html instanceof Nette\Templating\IFileTemplate || $html instanceof Nette\Application\UI\ITemplate)) {
         $basePath = dirname($html->getFile());
         $bc = TRUE;
     }
     $html = (string) $html;
     if ($basePath) {
         $cids = array();
         $matches = Strings::matchAll($html, '#(src\\s*=\\s*|background\\s*=\\s*|url\\()(["\']?)(?![a-z]+:|[/\\#])([^"\')\\s]+)#i', PREG_OFFSET_CAPTURE);
         if ($matches && isset($bc)) {
             trigger_error(__METHOD__ . '() missing second argument with image base path.', E_USER_WARNING);
         }
         foreach (array_reverse($matches) as $m) {
             $file = rtrim($basePath, '/\\') . '/' . urldecode($m[3][0]);
             if (!isset($cids[$file])) {
                 $cids[$file] = substr($this->addEmbeddedFile($file)->getHeader('Content-ID'), 1, -1);
             }
             $html = substr_replace($html, "{$m[1][0]}{$m[2][0]}cid:{$cids[$file]}", $m[0][1], strlen($m[0][0]));
         }
     }
     if ($this->getSubject() == NULL) {
         // intentionally ==
         $html = Strings::replace($html, '#<title>(.+?)</title>#is', function ($m) use(&$title) {
             $title = $m[1];
         });
         $this->setSubject(html_entity_decode($title, ENT_QUOTES, 'UTF-8'));
     }
     $this->html = ltrim(str_replace("\r", '', $html), "\n");
     if ($this->getBody() == NULL && $html != NULL) {
         // intentionally ==
         $this->setBody($this->buildText($html));
     }
     return $this;
 }
Exemplo n.º 9
0
 /**
  * Sets HTML body.
  * @param  string|Nette\Templating\ITemplate
  * @param  mixed base-path or FALSE to disable parsing
  * @return self
  */
 public function setHtmlBody($html, $basePath = NULL)
 {
     if ($html instanceof Nette\Templating\ITemplate || $html instanceof Nette\Application\UI\ITemplate) {
         $html->mail = $this;
         if ($basePath === NULL && ($html instanceof Nette\Templating\IFileTemplate || $html instanceof Nette\Application\UI\ITemplate)) {
             $basePath = dirname($html->getFile());
         }
         $html = $html->__toString(TRUE);
     }
     if ($basePath !== FALSE) {
         $cids = array();
         $matches = Strings::matchAll($html, '#(src\\s*=\\s*|background\\s*=\\s*|url\\()(["\']?)(?![a-z]+:|[/\\#])([^"\')\\s]+)#i', PREG_OFFSET_CAPTURE);
         foreach (array_reverse($matches) as $m) {
             $file = rtrim($basePath, '/\\') . '/' . $m[3][0];
             if (!isset($cids[$file])) {
                 $cids[$file] = substr($this->addEmbeddedFile($file)->getHeader('Content-ID'), 1, -1);
             }
             $html = substr_replace($html, "{$m[1][0]}{$m[2][0]}cid:{$cids[$file]}", $m[0][1], strlen($m[0][0]));
         }
     }
     $this->html = $html;
     if ($this->getSubject() == NULL && ($matches = Strings::match($html, '#<title>(.+?)</title>#is'))) {
         // intentionally ==
         $this->setSubject(html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'));
     }
     if ($this->getBody() == NULL && $html != NULL) {
         // intentionally ==
         $this->setBody($this->buildText($html));
     }
     return $this;
 }
Exemplo n.º 10
0
 /**
  * Logging navigation requested
  *
  * @param string $requestLine
  */
 private function logRequest($requestLine)
 {
     $requestLine = Strings::replace($requestLine, '[Navigation requested: ]');
     $requestLine = Strings::trim($requestLine);
     $matches = Strings::matchAll($requestLine, '~ ([^=]+)=([^,]+),?~');
     $request = [];
     foreach ($matches as $match) {
         $match[2] = $match[2] === 'true' ? true : ($match[2] === 'false' ? false : $match[2]);
         $request[$match[1]] = $match[2];
     }
     $this->requests[] = $request;
 }
Exemplo n.º 11
0
 /**
  * Builds HTML content.
  * @return void
  */
 protected function buildHtml()
 {
     if ($this->html instanceof Nette\Templating\ITemplate) {
         $this->html->mail = $this;
         if ($this->basePath === NULL && $this->html instanceof Nette\Templating\IFileTemplate) {
             $this->basePath = dirname($this->html->getFile());
         }
         $this->html = $this->html->__toString(TRUE);
     }
     if ($this->basePath !== FALSE) {
         $cids = array();
         $matches = Strings::matchAll($this->html, '#(src\\s*=\\s*|background\\s*=\\s*|url\\()(["\'])(?![a-z]+:|[/\\#])(.+?)\\2#i', PREG_OFFSET_CAPTURE);
         foreach (array_reverse($matches) as $m) {
             $file = rtrim($this->basePath, '/\\') . '/' . $m[3][0];
             if (!isset($cids[$file])) {
                 $cids[$file] = substr($this->addEmbeddedFile($file)->getHeader("Content-ID"), 1, -1);
             }
             $this->html = substr_replace($this->html, "{$m[1][0]}{$m[2][0]}cid:{$cids[$file]}{$m[2][0]}", $m[0][1], strlen($m[0][0]));
         }
     }
     if (!$this->getSubject() && ($matches = Strings::match($this->html, '#<title>(.+?)</title>#is'))) {
         $this->setSubject(html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'));
     }
 }
Exemplo n.º 12
0
 public static function matchAll($subject, $pattern, $flags = 0, $offset = 0)
 {
     return Nette\Utils\Strings::matchAll($subject, $pattern, $flags, $offset);
 }
Exemplo n.º 13
0
 /**
  * Parse mask and array of default values; initializes object.
  * @param  string
  * @param  array
  * @return void
  */
 private function setMask($mask, array $metadata)
 {
     $this->mask = $mask;
     // detect '//host/path' vs. '/abs. path' vs. 'relative path'
     if (preg_match('#(?:(https?):)?(//.*)#A', $mask, $m)) {
         $this->type = self::HOST;
         list(, $this->scheme, $mask) = $m;
     } elseif (substr($mask, 0, 1) === '/') {
         $this->type = self::PATH;
     } else {
         $this->type = self::RELATIVE;
     }
     foreach ($metadata as $name => $meta) {
         if (!is_array($meta)) {
             $metadata[$name] = $meta = [self::VALUE => $meta];
         }
         if (array_key_exists(self::VALUE, $meta)) {
             if (is_scalar($meta[self::VALUE])) {
                 $metadata[$name][self::VALUE] = (string) $meta[self::VALUE];
             }
             $metadata[$name]['fixity'] = self::CONSTANT;
         }
     }
     if (strpbrk($mask, '?<>[]') === FALSE) {
         $this->re = '#' . preg_quote($mask, '#') . '/?\\z#A';
         $this->sequence = [$mask];
         $this->metadata = $metadata;
         return;
     }
     // PARSE MASK
     // <parameter-name[=default] [pattern]> or [ or ] or ?...
     $parts = Strings::split($mask, '/<([^<>= ]+)(=[^<> ]*)? *([^<>]*)>|(\\[!?|\\]|\\s*\\?.*)/');
     $this->xlat = [];
     $i = count($parts) - 1;
     // PARSE QUERY PART OF MASK
     if (isset($parts[$i - 1]) && substr(ltrim($parts[$i - 1]), 0, 1) === '?') {
         // name=<parameter-name [pattern]>
         $matches = Strings::matchAll($parts[$i - 1], '/(?:([a-zA-Z0-9_.-]+)=)?<([^> ]+) *([^>]*)>/');
         foreach ($matches as list(, $param, $name, $pattern)) {
             // $pattern is not used
             if (isset(static::$styles['?' . $name])) {
                 $meta = static::$styles['?' . $name];
             } else {
                 $meta = static::$styles['?#'];
             }
             if (isset($metadata[$name])) {
                 $meta = $metadata[$name] + $meta;
             }
             if (array_key_exists(self::VALUE, $meta)) {
                 $meta['fixity'] = self::OPTIONAL;
             }
             unset($meta['pattern']);
             $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]);
             $metadata[$name] = $meta;
             if ($param !== '') {
                 $this->xlat[$name] = $param;
             }
         }
         $i -= 5;
     }
     // PARSE PATH PART OF MASK
     $brackets = 0;
     // optional level
     $re = '';
     $sequence = [];
     $autoOptional = TRUE;
     $aliases = [];
     do {
         $part = $parts[$i];
         // part of path
         if (strpbrk($part, '<>') !== FALSE) {
             throw new Nette\InvalidArgumentException("Unexpected '{$part}' in mask '{$mask}'.");
         }
         array_unshift($sequence, $part);
         $re = preg_quote($part, '#') . $re;
         if ($i === 0) {
             break;
         }
         $i--;
         $part = $parts[$i];
         // [ or ]
         if ($part === '[' || $part === ']' || $part === '[!') {
             $brackets += $part[0] === '[' ? -1 : 1;
             if ($brackets < 0) {
                 throw new Nette\InvalidArgumentException("Unexpected '{$part}' in mask '{$mask}'.");
             }
             array_unshift($sequence, $part);
             $re = ($part[0] === '[' ? '(?:' : ')?') . $re;
             $i -= 4;
             continue;
         }
         $pattern = trim($parts[$i]);
         $i--;
         // validation condition (as regexp)
         $default = $parts[$i];
         $i--;
         // default value
         $name = $parts[$i];
         $i--;
         // parameter name
         array_unshift($sequence, $name);
         if ($name[0] === '?') {
             // "foo" parameter
             $name = substr($name, 1);
             $re = $pattern ? '(?:' . preg_quote($name, '#') . "|{$pattern}){$re}" : preg_quote($name, '#') . $re;
             $sequence[1] = $name . $sequence[1];
             continue;
         }
         // pattern, condition & metadata
         if (isset(static::$styles[$name])) {
             $meta = static::$styles[$name];
         } else {
             $meta = static::$styles['#'];
         }
         if (isset($metadata[$name])) {
             $meta = $metadata[$name] + $meta;
         }
         if ($pattern == '' && isset($meta[self::PATTERN])) {
             $pattern = $meta[self::PATTERN];
         }
         if ($default !== '') {
             $meta[self::VALUE] = (string) substr($default, 1);
             $meta['fixity'] = self::PATH_OPTIONAL;
         }
         $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]);
         if (array_key_exists(self::VALUE, $meta)) {
             if (isset($meta['filterTable2'][$meta[self::VALUE]])) {
                 $meta['defOut'] = $meta['filterTable2'][$meta[self::VALUE]];
             } elseif (isset($meta[self::FILTER_OUT])) {
                 $meta['defOut'] = call_user_func($meta[self::FILTER_OUT], $meta[self::VALUE]);
             } else {
                 $meta['defOut'] = $meta[self::VALUE];
             }
         }
         $meta[self::PATTERN] = "#(?:{$pattern})\\z#A";
         // include in expression
         $aliases['p' . $i] = $name;
         $re = '(?P<p' . $i . '>(?U)' . $pattern . ')' . $re;
         if ($brackets) {
             // is in brackets?
             if (!isset($meta[self::VALUE])) {
                 $meta[self::VALUE] = $meta['defOut'] = NULL;
             }
             $meta['fixity'] = self::PATH_OPTIONAL;
         } elseif (!$autoOptional) {
             unset($meta['fixity']);
         } elseif (isset($meta['fixity'])) {
             // auto-optional
             $re = '(?:' . $re . ')?';
             $meta['fixity'] = self::PATH_OPTIONAL;
         } else {
             $autoOptional = FALSE;
         }
         $metadata[$name] = $meta;
     } while (TRUE);
     if ($brackets) {
         throw new Nette\InvalidArgumentException("Missing '[' in mask '{$mask}'.");
     }
     $this->aliases = $aliases;
     $this->re = '#' . $re . '/?\\z#A';
     $this->metadata = $metadata;
     $this->sequence = $sequence;
 }
 /**
  * @param \SplFileInfo $file
  */
 private function processPresenter($file)
 {
     $stream = fopen("safe://" . $file->getRealPath(), 'r');
     $content = fread($stream, filesize("safe://" . $file->getRealPath()));
     fclose($stream);
     $module = String::match($content, '~(^|;)\\s*namespace (?P<name>[A-z0-9_-]+)Module;~m');
     $module = $module['name'];
     $presenter = String::match($content, '~(^|;)\\s*class (?P<name>[A-z0-9_-]+)Presenter(\\s|$)~m');
     if ($presenter === NULL || $presenter['name'] === 'Error') {
         return FALSE;
     }
     $presenter = $presenter['name'];
     $actions = array();
     foreach (String::matchAll($content, '~function (action|render)(?P<name>[A-z0-9_-]+)(\\s|\\()~') as $action) {
         $action = lcfirst($action['name']);
         if (array_search($action, $actions) === FALSE) {
             $actions[] = $action;
         }
     }
     return array($module, $presenter, $actions);
 }
    /**
     * Parses phpDoc comment.
     * @param  string
     * @return array
     */
    private static function parseComment($comment)
    {
        static $tokens = array('true' => TRUE, 'false' => FALSE, 'null' => NULL, '' => TRUE);
        $res = array();
        $comment = preg_replace('#^\\s*\\*\\s?#ms', '', trim($comment, '/*'));
        $parts = preg_split('#^\\s*(?=@' . self::RE_IDENTIFIER . ')#m', $comment, 2);
        $description = trim($parts[0]);
        if ($description !== '') {
            $res['description'] = array($description);
        }
        $matches = Strings::matchAll(isset($parts[1]) ? $parts[1] : '', '~
				(?<=\\s|^)@(' . self::RE_IDENTIFIER . ')[ \\t]*      ##  annotation
				(
					\\((?>' . self::RE_STRING . '|[^\'")@]+)+\\)|  ##  (value)
					[^(@\\r\\n][^@\\r\\n]*|)                     ##  value
			~xi');
        foreach ($matches as $match) {
            list(, $name, $value) = $match;
            if (substr($value, 0, 1) === '(') {
                $items = array();
                $key = '';
                $val = TRUE;
                $value[0] = ',';
                while ($m = Strings::match($value, '#\\s*,\\s*(?>(' . self::RE_IDENTIFIER . ')\\s*=\\s*)?(' . self::RE_STRING . '|[^\'"),\\s][^\'"),]*)#A')) {
                    $value = substr($value, strlen($m[0]));
                    list(, $key, $val) = $m;
                    $val = rtrim($val);
                    if ($val[0] === "'" || $val[0] === '"') {
                        $val = substr($val, 1, -1);
                    } elseif (is_numeric($val)) {
                        $val = 1 * $val;
                    } else {
                        $lval = strtolower($val);
                        $val = array_key_exists($lval, $tokens) ? $tokens[$lval] : $val;
                    }
                    if ($key === '') {
                        $items[] = $val;
                    } else {
                        $items[$key] = $val;
                    }
                }
                $value = count($items) < 2 && $key === '' ? $val : $items;
            } else {
                $value = trim($value);
                if (is_numeric($value)) {
                    $value = 1 * $value;
                } else {
                    $lval = strtolower($value);
                    $value = array_key_exists($lval, $tokens) ? $tokens[$lval] : $value;
                }
            }
            $class = $name . 'Annotation';
            if (self::$useAnnotationClasses && class_exists($class)) {
                $res[$name][] = new $class(is_array($value) ? $value : array('value' => $value));
            } else {
                $res[$name][] = is_array($value) ? Nette\ArrayHash::from($value) : $value;
            }
        }
        return $res;
    }
Exemplo n.º 16
0
    /**
     * Sets HTML body.
     * @param  string
     * @param  mixed base-path
     * @return self
     */
    public function setHtmlBody($html, $basePath = NULL)
    {
        $html = (string) $html;
        if ($basePath) {
            $cids = [];
            $matches = Strings::matchAll($html, '#
					(<img[^<>]*\\s src\\s*=\\s*
					|<body[^<>]*\\s background\\s*=\\s*
					|<[^<>]+\\s style\\s*=\\s* ["\'][^"\'>]+[:\\s] url\\(
					|<style[^>]*>[^<]+ [:\\s] url\\()
					(["\']?)(?![a-z]+:|[/\\#])([^"\'>)\\s]+)
					|\\[\\[ ([\\w()+./@~-]+) \\]\\]
				#ix', PREG_OFFSET_CAPTURE);
            foreach (array_reverse($matches) as $m) {
                $file = rtrim($basePath, '/\\') . '/' . (isset($m[4]) ? $m[4][0] : urldecode($m[3][0]));
                if (!isset($cids[$file])) {
                    $cids[$file] = substr($this->addEmbeddedFile($file)->getHeader('Content-ID'), 1, -1);
                }
                $html = substr_replace($html, "{$m[1][0]}{$m[2][0]}cid:{$cids[$file]}", $m[0][1], strlen($m[0][0]));
            }
        }
        if ($this->getSubject() == NULL) {
            // intentionally ==
            $html = Strings::replace($html, '#<title>(.+?)</title>#is', function ($m) use(&$title) {
                $title = $m[1];
            });
            $this->setSubject(html_entity_decode($title, ENT_QUOTES, 'UTF-8'));
        }
        $this->html = ltrim(str_replace("\r", '', $html), "\n");
        if ($this->getBody() == NULL && $html != NULL) {
            // intentionally ==
            $this->setBody($this->buildText($html));
        }
        return $this;
    }
Exemplo n.º 17
0
 /**
  * Expands cookie header "Set-Cookie"
  *   user_time=1327581075; expires=Sat, 25-Feb-2012 12:31:15 GMT; path=/
  * to array
  *
  * @param string $cookie
  *
  * @return array|NULL
  */
 public static function readCookie($cookie)
 {
     if (!($m = Strings::matchAll($cookie, '~(?P<name>[^;=\\s]+)(?:=(?P<value>[^;]*))?~i'))) {
         return NULL;
     }
     $first = array_shift($m);
     $cookie = array('name' => urldecode($first['name']), 'value' => urldecode($first['value']));
     foreach ($m as $found) {
         $cookie[$found['name']] = !empty($found['value']) ? $found['value'] : TRUE;
     }
     return $cookie;
 }
Exemplo n.º 18
0
 /**
  * Converts raw TXT to internal CSV
  */
 private function raw2csv()
 {
     $verifier = new Verifier();
     $lines = preg_split('/[\\r\\n]+/', $this->_sourceData);
     foreach ($lines as $line) {
         // if it's not a blank line, and it's not the header row
         if ($line == '' || Strings::length($line) < 10 || Strings::startsWith($line, 'SEPA Country') || Strings::startsWith($line, 'Name of country')) {
             continue;
         }
         // assigned fields to named variables
         list($countryName, $countryCode, $domesticExample, $bban, $bbanStructure, $bbanLength, $bbanBiPosition, $bbanBiLength, $bbanBiExample, $bbanExample, $iban, $ibanStructure, $ibanLength, $ibanElectronicExample, $ibanPrintExample, $countrySepa, $contactDetails) = array_map(function ($item) {
             return trim(trim($item, '"'), ' ');
         }, explode("\t", $line));
         // sanitise
         $countryCode = Strings::upper(substr($countryCode, 0, 2));
         // sanitise comments away
         $bbanStructure = Strings::replace($bbanStructure, '/[:;]/');
         // errors seen in Germany, Hungary entries
         $ibanStructure = Strings::replace($ibanStructure, '/, .*$/');
         // duplicates for FO, GL seen in DK
         $ibanElectronicExample = Strings::replace($ibanElectronicExample, '/, .*$/');
         // duplicates for FO, GL seen in DK
         switch ($countryCode) {
             case 'MU':
                 $ibanElectronicExample = str_replace(' ', '', $ibanElectronicExample);
                 // MU example has a spurious space
                 break;
             case 'CZ':
                 $ibanElectronicExample = Strings::replace($ibanElectronicExample, '/ \\{10,}+$/');
                 // extra example for CZ
                 $ibanPrintExample = Strings::replace($ibanPrintExample, '/^(CZ.. .... .... .... .... ....).*$/', '$1');
                 // extra example
                 break;
             case 'FI':
                 // remove additional example
                 $ibanElectronicExample = Strings::replace($ibanElectronicExample, '/ or .*$/');
                 // fix bban example to remove verbosity and match domestic example
                 $bban = '12345600000785';
                 break;
         }
         $ibanPrintExample = Strings::replace($ibanPrintExample, '/, .*$/');
         // calculate $bban_regex from $bban_structure
         $bbanRegex = $this->swift2regex($bbanStructure);
         // calculate $iban_regex from $iban_structure
         $ibanRegex = $this->swift2regex($ibanStructure);
         // calculate numeric $bban_length
         $bbanLength = Strings::replace($bbanLength, '/[^\\d]/');
         // calculate numeric $iban_length
         $ibanLength = Strings::replace($ibanLength, '/[^\\d]/');
         /*
          * calculate bban_bankid_<start|stop>_offset
          * .... First we have to parse the freetext $bban_bi_position, eg: 
          * Bank Identifier 1-3, Branch Identifier
          * Position 1-2
          * Positions 1-2
          * Positions 1-3
          * Positions 1-3 ;Branch is not available
          * Positions 1-3, Branch identifier
          * Positions 1-3, Branch identifier positions
          * Positions 1-4
          * Positions 1-4, Branch identifier
          * Positions 1-4, Branch identifier positions
          * Positions 1-5
          * Positions 1-5 (positions 1-2 bank identifier; positions 3-5 branch identifier). In case of payment institutions Positions 1-5, Branch identifier positions
          * Positions 1-6,  Branch identifier positions
          * Positions 1-6. First two digits of bank identifier indicate the bank or banking group (For example, 1 or 2 for Nordea, 31 for Handelsbanken, 5 for cooperative banks etc)
          * Positions 1-7
          * Positions 1-8
          * Positions 2-6, Branch identifier positions
          * positions 1-3, Branch identifier positions
          *
          *  ... our algorithm is as follows:
          *   - find all <digit>-<digit> tokens
          */
         $matches = Strings::matchAll($bbanBiPosition, '/(\\d)-(\\d\\d?)/', PREG_PATTERN_ORDER);
         // - discard overlaps ({1-5,1-2,3-5} becomes {1-2,3-5})
         $tmptokens = [];
         for ($j = 0; $j < count($matches[0]); $j++) {
             $from = $matches[1][$j];
             $to = $matches[2][$j];
             // (if we don't yet have a match starting here, or it goes further,
             //  overwrite the match-from-this-position record)
             if (!isset($tmptokens[$from]) || $to < $tmptokens[$from]) {
                 $tmptokens[$from] = $to;
             }
         }
         unset($matches);
         // done
         // - assume the token starting from position 1 is the bank identifier
         //  (or, if it does not exist, the token starting from position 2)
         $bbanBankidStartOffset = 0;
         // decrement 1 on assignment
         if (isset($tmptokens[1])) {
             $bbanBankidStopOffset = $tmptokens[1] - 1;
             // decrement 1 on assignment
             unset($tmptokens[1]);
         } else {
             $bbanBankidStopOffset = $tmptokens[2] - 1;
             // decrement 1 on assignment
             unset($tmptokens[2]);
         }
         // - assume any subsequent token, if present, is the branch identifier.
         $tmpkeys = array_keys($tmptokens);
         $start = array_shift($tmpkeys);
         unset($tmpkeys);
         //done
         $bbanBranchidStartOffset = $bbanBranchidStopOffset = '';
         if ($start != '') {
             // we have a branch identifier!
             $bbanBranchidStartOffset = $start - 1;
             $bbanBranchidStopOffset = $tmptokens[$start] - 1;
         } else {
             /*
              * (note: this codepath occurs for around two thirds of all records)
              * we have not yet found a branch identifier. HOWEVER, we can analyse the
              * structure of the BBAN to determine whether there is more than one
              * remaining non-tiny field (tiny fields on the end of a BBAN typically
              * being checksums) and, if so, assume that the first/shorter one is the branch identifier.
              */
             $reducedBbanStructure = Strings::replace($bbanStructure, '/^\\d+![nac]/');
             $tokens = $this->swiftTokenize($reducedBbanStructure, TRUE);
             // discard any tokens of length 1 or 2
             for ($t = 0; $t < count($tokens[0]); $t++) {
                 $tokens['discarded'][$t] = $tokens[1][$t] < 3 ? 1 : 0;
             }
             // interesting fields are those that are not discarded...
             $interestingFieldCount = !isset($tokens['discarded']) ? count($tokens[0]) : count($tokens[0]) - count($tokens['discarded']);
             // ...if we have at least two of them, there's a branchid-type field
             if ($interestingFieldCount >= 2) {
                 // now loop through until we assign the branchid start offset
                 // (this occurs just after the first non-discarded field)
                 $found = FALSE;
                 for ($f = 0; !$found && $f < count($tokens[0]); $f++) {
                     // if this is a non-discarded token, of >2 length...
                     if ((!isset($tokens['discarded'][$f]) || $tokens['discarded'][$f] != 1) && $tokens[1][$f] > 2) {
                         // ... then assign.
                         $preOffset = $bbanBankidStopOffset + 1;
                         // this is the offset before we reduced the structure to remove the bankid field
                         $bbanBranchidStartOffset = $preOffset + $tokens['offset'][$f];
                         $bbanBranchidStopOffset = $preOffset + $tokens['offset'][$f] + $tokens[1][$f] - 1;
                         // decrement by one on assignment
                         $found = TRUE;
                     }
                 }
             }
         }
         /*
          * calculate 1=Yes, 0=No for $country_sepa
          * note: This is buggy due to the free inclusion of random text by the registry publishers.
          *  Notably it requires modification for places like Finland and Portugal where these comments are known to exist.
          */
         $countrySepa = Strings::lower($countrySepa) == 'yes';
         // set registry edition
         $registryEdition = date('Y-m-d');
         // now prepare generate our registry lines...
         $toGenerate = [$countryCode => $countryName];
         switch ($countryCode) {
             case 'DK':
                 $toGenerate = ['DK' => $countryName, 'FO' => 'Faroe Islands', 'GL' => 'Greenland'];
                 break;
             case 'FR':
                 $toGenerate = ['FR' => $countryName, 'BL' => 'Saint Barthelemy', 'GF' => 'French Guyana', 'GP' => 'Guadelope', 'MF' => 'Saint Martin (French Part)', 'QM' => 'Martinique', 'RE' => 'Reunion', 'PF' => 'French Polynesia', 'TF' => 'French Sounthern Territories', 'YT' => 'Mayotte', 'NC' => 'New Caledonia', 'PM' => 'Saint Pierre et Miquelon', 'WF' => 'Wallis and Futuna Islands'];
                 break;
         }
         // output loop
         foreach ($toGenerate as $countryCode => $countryName) {
             $ibanElectronicExample = $verifier->setChecksum($countryCode . substr($ibanElectronicExample, 2));
             $ibanStructure = $countryCode . substr($ibanStructure, 2);
             $ibanRegex = '^' . $countryCode . substr($ibanRegex, 3);
             $this->_csvData[] = [$countryCode, $countryName, $domesticExample, $bbanExample, $bbanStructure, $bbanRegex, $bbanLength, $ibanElectronicExample, $ibanStructure, $ibanRegex, $ibanLength, $bbanBankidStartOffset, $bbanBankidStopOffset, $bbanBranchidStartOffset, $bbanBranchidStopOffset, $registryEdition, $countrySepa];
         }
     }
 }
 /**
  * Parse mask and array of default values; initializes object.
  * @param  string
  * @param  array
  * @return void
  */
 private function setMask($mask, array $metadata)
 {
     $this->mask = $mask;
     // detect '//host/path' vs. '/abs. path' vs. 'relative path'
     if (substr($mask, 0, 2) === '//') {
         $this->type = self::HOST;
     } elseif (substr($mask, 0, 1) === '/') {
         $this->type = self::PATH;
     } else {
         $this->type = self::RELATIVE;
     }
     foreach ($metadata as $name => $meta) {
         if (!is_array($meta)) {
             $metadata[$name] = array(self::VALUE => $meta, 'fixity' => self::CONSTANT);
         } elseif (array_key_exists(self::VALUE, $meta)) {
             $metadata[$name]['fixity'] = self::CONSTANT;
         }
     }
     // PARSE MASK
     // <parameter-name[=default] [pattern] [#class]> or [ or ] or ?...
     $parts = Strings::split($mask, '/<([^>#= ]+)(=[^># ]*)? *([^>#]*)(#?[^>\\[\\]]*)>|(\\[!?|\\]|\\s*\\?.*)/');
     $this->xlat = array();
     $i = count($parts) - 1;
     // PARSE QUERY PART OF MASK
     if (isset($parts[$i - 1]) && substr(ltrim($parts[$i - 1]), 0, 1) === '?') {
         // name=<parameter-name [pattern][#class]>
         $matches = Strings::matchAll($parts[$i - 1], '/(?:([a-zA-Z0-9_.-]+)=)?<([^># ]+) *([^>#]*)(#?[^>]*)>/');
         foreach ($matches as $match) {
             list(, $param, $name, $pattern, $class) = $match;
             // $pattern is not used
             if ($class !== '') {
                 if (!isset(static::$styles[$class])) {
                     throw new Nette\InvalidStateException("Parameter '{$name}' has '{$class}' flag, but Route::\$styles['{$class}'] is not set.");
                 }
                 $meta = static::$styles[$class];
             } elseif (isset(static::$styles['?' . $name])) {
                 $meta = static::$styles['?' . $name];
             } else {
                 $meta = static::$styles['?#'];
             }
             if (isset($metadata[$name])) {
                 $meta = $metadata[$name] + $meta;
             }
             if (array_key_exists(self::VALUE, $meta)) {
                 $meta['fixity'] = self::OPTIONAL;
             }
             unset($meta['pattern']);
             $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]);
             $metadata[$name] = $meta;
             if ($param !== '') {
                 $this->xlat[$name] = $param;
             }
         }
         $i -= 6;
     }
     // PARSE PATH PART OF MASK
     $brackets = 0;
     // optional level
     $re = '';
     $sequence = array();
     $autoOptional = TRUE;
     do {
         array_unshift($sequence, $parts[$i]);
         $re = preg_quote($parts[$i], '#') . $re;
         if ($i === 0) {
             break;
         }
         $i--;
         $part = $parts[$i];
         // [ or ]
         if ($part === '[' || $part === ']' || $part === '[!') {
             $brackets += $part[0] === '[' ? -1 : 1;
             if ($brackets < 0) {
                 throw new Nette\InvalidArgumentException("Unexpected '{$part}' in mask '{$mask}'.");
             }
             array_unshift($sequence, $part);
             $re = ($part[0] === '[' ? '(?:' : ')?') . $re;
             $i -= 5;
             continue;
         }
         $class = $parts[$i];
         $i--;
         // validation class
         $pattern = trim($parts[$i]);
         $i--;
         // validation condition (as regexp)
         $default = $parts[$i];
         $i--;
         // default value
         $name = $parts[$i];
         $i--;
         // parameter name
         array_unshift($sequence, $name);
         if ($name[0] === '?') {
             // "foo" parameter
             $name = substr($name, 1);
             $re = $pattern ? '(?:' . preg_quote($name, '#') . "|{$pattern}){$re}" : preg_quote($name, '#') . $re;
             $sequence[1] = $name . $sequence[1];
             continue;
         }
         // check name (limitation by regexp)
         if (preg_match('#[^a-z0-9_-]#i', $name)) {
             throw new Nette\InvalidArgumentException("Parameter name must be alphanumeric string due to limitations of PCRE, '{$name}' given.");
         }
         // pattern, condition & metadata
         if ($class !== '') {
             if (!isset(static::$styles[$class])) {
                 throw new Nette\InvalidStateException("Parameter '{$name}' has '{$class}' flag, but Route::\$styles['{$class}'] is not set.");
             }
             $meta = static::$styles[$class];
         } elseif (isset(static::$styles[$name])) {
             $meta = static::$styles[$name];
         } else {
             $meta = static::$styles['#'];
         }
         if (isset($metadata[$name])) {
             $meta = $metadata[$name] + $meta;
         }
         if ($pattern == '' && isset($meta[self::PATTERN])) {
             $pattern = $meta[self::PATTERN];
         }
         if ($default !== '') {
             $meta[self::VALUE] = (string) substr($default, 1);
             $meta['fixity'] = self::PATH_OPTIONAL;
         }
         $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]);
         if (array_key_exists(self::VALUE, $meta)) {
             if (isset($meta['filterTable2'][$meta[self::VALUE]])) {
                 $meta['defOut'] = $meta['filterTable2'][$meta[self::VALUE]];
             } elseif (isset($meta[self::FILTER_OUT])) {
                 $meta['defOut'] = call_user_func($meta[self::FILTER_OUT], $meta[self::VALUE]);
             } else {
                 $meta['defOut'] = $meta[self::VALUE];
             }
         }
         $meta[self::PATTERN] = "#(?:{$pattern})\\z#A" . ($this->flags & self::CASE_SENSITIVE ? '' : 'iu');
         // include in expression
         $re = '(?P<' . str_replace('-', '___', $name) . '>(?U)' . $pattern . ')' . $re;
         // str_replace is dirty trick to enable '-' in parameter name
         if ($brackets) {
             // is in brackets?
             if (!isset($meta[self::VALUE])) {
                 $meta[self::VALUE] = $meta['defOut'] = NULL;
             }
             $meta['fixity'] = self::PATH_OPTIONAL;
         } elseif (!$autoOptional) {
             unset($meta['fixity']);
         } elseif (isset($meta['fixity'])) {
             // auto-optional
             $re = '(?:' . $re . ')?';
             $meta['fixity'] = self::PATH_OPTIONAL;
         } else {
             $autoOptional = FALSE;
         }
         $metadata[$name] = $meta;
     } while (TRUE);
     if ($brackets) {
         throw new Nette\InvalidArgumentException("Missing closing ']' in mask '{$mask}'.");
     }
     $this->re = '#' . $re . '/?\\z#A' . ($this->flags & self::CASE_SENSITIVE ? '' : 'iu');
     $this->metadata = $metadata;
     $this->sequence = $sequence;
 }
Exemplo n.º 20
0
 public static function matchAll($re, $str, $flags = 0, $offset = 0)
 {
     return parent::matchAll($str, $re, $flags, $offset);
 }