/**
  * Generate a path to the mercurial repo for the file
  *
  * @param  string $locale locale code
  * @param  string $repo   repository name
  * @param  string $path   Entity name representing the local file
  * @return string Path to the file in remote mercurial repository
  */
 public static function hgPath($locale, $repo, $path)
 {
     $url = 'https://hg.mozilla.org';
     // remove entity from path and store it in a variable
     $path = explode(':', $path);
     $path = $path[0];
     $path = explode('/', $path);
     $entity_file = array_pop($path);
     $path = implode('/', $path);
     $exploded_path = explode('/', $path);
     $base_folder = $exploded_path[0];
     if (Strings::startsWith($repo, 'gaia') || in_array($base_folder, ['apps', 'shared', 'showcase_apps', 'test_apps', 'test_external_apps'])) {
         $locale = Project::getLocaleInContext($locale, $repo);
         if ($repo == 'gaia') {
             $url .= '/gaia-l10n/' . $locale . '/file/default/';
         } else {
             $version = str_replace('gaia_', '', $repo);
             $url .= '/releases/gaia-l10n/v' . $version . '/' . $locale . '/file/default/';
         }
         return $url . $path . '/' . $entity_file;
     }
     $en_US_Folder_Mess = ['b2g/branding/official/', 'b2g/branding/unofficial/', 'b2g/', 'netwerk/', 'embedding/android/', 'testing/extensions/community/chrome/', 'intl/', 'extensions/spellcheck/', 'services/sync/', 'mobile/android/branding/aurora/', 'mobile/android/branding/official/', 'mobile/android/branding/nightly/', 'mobile/android/branding/unofficial/', 'mobile/android/branding/beta/', 'mobile/android/base/', 'mobile/android/', 'mobile/', 'security/manager/', 'toolkit/content/tests/fennec-tile-testapp/chrome/', 'toolkit/', 'browser/branding/aurora/', 'browser/branding/official/', 'browser/branding/nightly/', 'browser/branding/unofficial/', 'browser/', 'devtools/client/', 'devtools/shared/', 'layout/tools/layout-debug/ui/', 'dom/', 'webapprt/', 'chat/', 'suite/', 'other-licenses/branding/thunderbird/', 'mail/branding/aurora/', 'mail/branding/nightly/', 'mail/', 'mail/test/resources/mozmill/mozmill/extension/', 'editor/ui/', 'calendar/'];
     // Destop repos
     if ($locale != 'en-US') {
         if ($repo == 'central') {
             $url .= '/l10n-central/' . $locale . '/file/default/';
         } else {
             $url .= '/releases/l10n/mozilla-' . $repo . '/' . $locale . '/file/default/';
         }
     } else {
         if (in_array($base_folder, ['calendar', 'chat', 'editor', 'ldap', 'mail', 'mailnews', 'suite'])) {
             $repo_base = 'comm';
         } else {
             $repo_base = 'mozilla';
         }
         if ($repo == 'central') {
             $url .= "/{$repo_base}-central/file/default/";
         } else {
             $url .= "/releases/{$repo_base}-{$repo}/file/default/";
         }
         $loop = true;
         while ($loop && count($exploded_path) > 0) {
             if (in_array(implode('/', $exploded_path) . '/', $en_US_Folder_Mess)) {
                 $path_part1 = implode('/', $exploded_path) . '/locales/en-US';
                 $pattern = preg_quote(implode('/', $exploded_path), '/');
                 $path = preg_replace('/' . $pattern . '/', $path_part1, $path, 1);
                 $loop = false;
                 break;
             } else {
                 array_pop($exploded_path);
             }
         }
         if ($loop == true) {
             $path = explode('/', $path);
             $category = array_shift($path);
             $path = $category . '/locales/en-US/' . implode('/', $path);
         }
     }
     return $url . $path . '/' . $entity_file;
 }
Exemple #2
0
 /**
  *
  * Loads strings from a .lang file into an array. File format is:
  *  ;String in english
  *  translated string
  *
  * @param  string  $file             .lang file to load
  * @param  boolean $reference_locale True if the current locale is the reference locale
  * @return array   Array of strings as [original => translation]
  */
 public static function getStrings($file, $reference_locale)
 {
     // get all the lines in an array
     $f = self::getFile($file);
     $strings = [];
     for ($i = 0, $lines = count($f); $i < $lines; $i++) {
         // skip comments and metadata
         if (Strings::startsWith($f[$i], '#')) {
             continue;
         }
         if (Strings::startsWith($f[$i], ';') && !empty($f[$i + 1])) {
             $english = trim(substr($f[$i], 1));
             if (Strings::startsWith($f[$i + 1], '#') || Strings::startsWith($f[$i + 1], ';')) {
                 /* String is not translated, next line is a comment or
                  * the next source string. I consider the string untranslated
                  */
                 $translation = $english;
             } else {
                 // Next line is an actual translation
                 $translation = trim($f[$i + 1]);
             }
             // If untranslated, I need to store an empty string as translation
             // unless it's the reference locale
             if ($reference_locale) {
                 $strings[$english] = $english;
             } else {
                 $strings[$english] = $translation == $english ? '' : $translation;
             }
             $i++;
         }
     }
     return $strings;
 }
Exemple #3
0
 /**
  * Contains returns true if a base path contains a needle.
  *
  * Note that `realpath` is used on both base and needle: they need to exist or false is returned.
  *
  * Use this for avoiding directory traversal outside of a base path.
  *
  * @param string $base   Path to base directory.
  * @param string $needle Needle that must exist within the base directory.
  *
  * @return bool True if both exist and needle does not escape the base folder.
  */
 public static function contains($base, $needle)
 {
     $realBase = realpath($base);
     $needle = realpath($needle);
     if ($realBase === false || $needle === false) {
         return false;
     }
     return Strings::startsWith($needle, $base);
 }
Exemple #4
0
 /**
  * Return the list of files in a folder as an array.
  * Hidden files starting with a dot (.svn, .htaccess...) are ignored.
  *
  * @param  string $folder         the directory we want to scan
  * @param  array  $excluded_files Files to exclude from results
  * @return array  Files in the folder
  */
 public static function getFilenamesInFolder($folder, $excluded_files = [])
 {
     /*
         Here we exclude by default hidden files starting with a dot and
         the . and .. symbols for directories
     */
     $files = array_filter(scandir($folder), function ($item) {
         return !Strings::startsWith($item, '.');
     });
     return array_diff($files, $excluded_files);
 }
Exemple #5
0
 public function login()
 {
     if (isset($_GET['returnto']) && Strings::startsWith($_GET['returnto'], '/')) {
         $returnto = $_GET['returnto'];
     } else {
         $returnto = (string) new URL();
     }
     if ($_SERVER['REQUEST_METHOD'] === 'POST') {
         $query = db()->table('user')->getAll();
         $query->group()->addRestriction('email', $_POST['username'])->addRestriction('usernames', db()->table('username')->get('name', $_POST['username'])->addRestriction('expires', NULL, 'IS'))->endGroup();
         $user = $query->fetch();
         if ($user && $user->checkPassword($_POST['password'])) {
             $session = Session::getInstance();
             $session->lock($user->_id);
             return $this->response->getHeaders()->redirect($returnto);
         } else {
             $this->view->set('message', 'Username or password did not match');
         }
     }
     $this->view->set('returnto', $returnto);
 }
 /**
  * Search for strings with variables differences
  * @param  array  $tmx_source      TMX file as reference
  * @param  array  $tmx_target      TMX file for the locale to compare
  * @param  string $repo            Name of the repo to determine the right set of regexps
  * @param  array  $ignored_strings Optional list of ignored strings, default empty
  * @return array  List of entity names not matching source
  */
 public static function differences($tmx_source, $tmx_target, $repo, $ignored_strings = [])
 {
     $pattern_mismatch = [];
     switch ($repo) {
         case Strings::startsWith($repo, 'gaia'):
             $patterns = ['l10njs' => '/\\{\\{\\s*([a-z0-9_]+)\\s*\\}\\}/iu'];
             break;
         case 'firefox_ios':
             $patterns = ['ios' => '/(%(?:[0-9]+\\$){0,1}@)/i'];
             break;
         default:
             $patterns = ['dtd' => '/&([a-z0-9\\.]+);/i', 'printf' => '/(%(?:[0-9]+\\$){0,1}(?:[0-9].){0,1}(S))/i', 'properties' => '/(?<!%[0-9])\\$[a-z0-9\\.]+\\b/i', 'l10njs' => '/\\{\\{\\s*([a-z0-9_]+)\\s*\\}\\}/iu'];
             break;
     }
     foreach ($patterns as $pattern_name => $pattern) {
         foreach ($tmx_source as $key => $source) {
             if (isset($tmx_target[$key]) && $tmx_target[$key] != '' && !in_array($key, $ignored_strings)) {
                 // Check variables only if the translation exists and
                 // the string is not in the list of strings to ignore
                 $translation = $tmx_target[$key];
                 $wrong_variable = false;
                 preg_match_all($pattern, $source, $matches_source);
                 preg_match_all($pattern, $translation, $matches_translation);
                 if (count($matches_source[0]) > 0) {
                     foreach ($matches_source[0] as $var_source) {
                         if (!in_array($var_source, $matches_translation[0])) {
                             $wrong_variable = true;
                         }
                         // For l10n.js {{n}} == {{ n }}
                         if ($pattern_name == 'l10njs' && $wrong_variable) {
                             // Trim whitespaces and sort variables alphabetically
                             $trimmed_source_vars = array_map('trim', $matches_source[1]);
                             sort($trimmed_source_vars);
                             $trimmed_source_trans = array_map('trim', $matches_translation[1]);
                             sort($trimmed_source_trans);
                             if ($trimmed_source_vars === $trimmed_source_trans) {
                                 $wrong_variable = false;
                             }
                         }
                     }
                 }
                 if ($pattern_name == 'printf') {
                     /*
                      * Check ordered vs unordered variables. The pattern
                      * regular expression returns "S" or "s" as second group
                      * for each variable, I can use it to check for case
                      * differences ("s" vs "S") which are not allowed.
                      */
                     preg_match_all('/%(?:[0-9]+\\$){1}(?:[0-9].){0,1}S/i', $translation, $matches_ordered_trans);
                     preg_match_all('/%(?:0.){0,1}S/i', $translation, $matches_unordered_trans);
                     if (count($matches_ordered_trans[0]) > 0 && count($matches_unordered_trans[0]) > 0) {
                         // Strings can't mix ordered and unordered variables
                         $wrong_variable = true;
                     } else {
                         if (count($matches_translation[0]) == count($matches_source[0]) && $matches_translation[2] === $matches_source[2]) {
                             // Same number of variables and case, I assume the string is OK
                             $wrong_variable = false;
                         }
                     }
                 }
                 if ($wrong_variable) {
                     $pattern_mismatch[] = $key;
                 }
             }
         }
     }
     return $pattern_mismatch;
 }
Exemple #7
0
    /**
     * Handles CONTEXT_TAG.
     */
    private function contextTag()
    {
        $matches = $this->match('~
			(?P<end>\\ ?/?>)([ \\t]*\\n)?|  ##  end of HTML tag
			' . $this->macroRe . '|          ##  macro tag
			\\s*(?P<attr>[^\\s/>={]+)(?:\\s*=\\s*(?P<value>["\']|[^\\s/>{]+))? ## begin of HTML attribute
		~xsi');
        if (!empty($matches['end'])) {
            // end of HTML tag />
            $this->addToken(LatteToken::HTML_TAG_END, $matches[0]);
            $this->setContext(!$this->xmlMode && in_array($this->lastHtmlTag, array('script', 'style')) ? self::CONTEXT_CDATA : self::CONTEXT_TEXT);
        } elseif (isset($matches['attr']) && $matches['attr'] !== '') {
            // HTML attribute
            $token = $this->addToken(LatteToken::HTML_ATTRIBUTE, $matches[0]);
            $token->name = $matches['attr'];
            $token->value = isset($matches['value']) ? $matches['value'] : '';
            if ($token->value === '"' || $token->value === "'") {
                // attribute = "'
                if (Strings::startsWith($token->name, self::N_PREFIX)) {
                    $token->value = '';
                    if ($m = $this->match('~(.*?)' . $matches['value'] . '~xsi')) {
                        $token->value = $m[1];
                        $token->text .= $m[0];
                    }
                } else {
                    $this->setContext(self::CONTEXT_ATTRIBUTE, $matches['value']);
                }
            }
        }
        return $matches;
    }
Exemple #8
0
 /**
  * Ověří, zda soubor je v zadaném adresáři.
  * @param string $file
  * @param string $dir
  * @return bool
  */
 static function isFileInDir($file, $dir)
 {
     if (!Strings::endsWith($dir, "/")) {
         $dir .= "/";
     }
     return Strings::startsWith($file, $dir);
 }
Exemple #9
0
 public static function convertFileName($fileName, $pattern)
 {
     if (empty($pattern)) {
         return $fileName;
     }
     $new = preg_replace_callback("({[\\w\\s\\[\\],-_]+})", function ($p) use($fileName) {
         $a = $p[0];
         if ($a == '{md5}') {
             return md5($fileName);
         } else {
             if ($a == '{ext}') {
                 return substr(strrchr($fileName, '.'), 1);
             } else {
                 if ($a == '{origin}') {
                     $ext = strrchr($fileName, '.');
                     return substr($fileName, 0, strlen($fileName) - strlen($ext));
                 } else {
                     if (Strings::startsWith($a, '{date')) {
                         preg_match('(\\[.*\\])', $a, $p);
                         $pattern = trim($p[0], "[]");
                         return date($pattern, time());
                     } else {
                         if ($a == '{unix_timestamp}') {
                             return time();
                         } else {
                             if (Strings::startsWith($a, '{random')) {
                                 preg_match('(\\[.*\\])', $a, $p);
                                 $pattern = trim($p[0], "[]");
                                 $r = explode(',', $pattern);
                                 return rand($r[0], $r[1]);
                             }
                         }
                     }
                 }
             }
         }
         return $a;
     }, $pattern);
     return $new;
 }
Exemple #10
0
 /**
  * Adds prefix to the string, if string does not start with the prefix already.
  *
  * Example:
  * <code>
  * $string = 'Daenerys Targaryen';
  * $stringWithPrefix = Strings::appendMissingPrefix($string, 'Daenerys ');
  * </code>
  * Result:
  * <code>
  * Daenerys Targaryen
  * </code>
  *
  * @param string $string
  * @param string $prefix
  * @return string
  */
 public static function prependIfMissing($string, $prefix)
 {
     if (Strings::startsWith($string, $prefix)) {
         return $string;
     }
     return Strings::appendPrefix($string, $prefix);
 }
Exemple #11
0
 /**
  * Return the correct locale code based on context
  * For example: given "es", returns "es-ES" for Bugzilla,
  * "es" for Gaia, "es-ES" for other repos.
  *
  * @param  string $locale  Name of the current locale
  * @param  string $context The context we need to use this locale in
  * @return string Locale code to use in the requested context
  */
 public static function getLocaleInContext($locale, $context)
 {
     $locale_mappings = [];
     // Bugzilla locales
     $locale_mappings['bugzilla'] = ['es' => 'es-ES', 'gu' => 'gu-IN', 'pa' => 'pa-IN', 'sr-Cyrl' => 'sr', 'sr-Latn' => 'sr'];
     // Gaia locales
     $locale_mappings['gaia'] = ['es-AR' => 'es', 'es-CL' => 'es', 'es-ES' => 'es', 'es-MX' => 'es', 'gu-IN' => 'gu', 'pa-IN' => 'pa', 'sr' => 'sr-Cyrl'];
     // Use Gaia mapping for all Gaia repositories
     if (Strings::startsWith($context, 'gaia')) {
         $context = 'gaia';
     }
     // Firefox for iOS
     $locale_mappings['firefox_ios'] = ['es-AR' => 'es', 'es-ES' => 'es'];
     // For other contexts use the same as Bugzilla
     $locale_mappings['other'] = $locale_mappings['bugzilla'];
     // Fallback to 'other' if context doesn't exist in $locale_mappings
     $context = array_key_exists($context, $locale_mappings) ? $context : 'other';
     $locale = array_key_exists($locale, $locale_mappings[$context]) ? $locale_mappings[$context][$locale] : $locale;
     return $locale;
 }
Exemple #12
0
 public static function isearchStartsWith($needle, array $haystack)
 {
     foreach ($haystack as $key => $val) {
         if (Strings::startsWith(strtolower($val), strtolower($needle))) {
             return $key;
         }
     }
     return false;
 }
Exemple #13
0
 /**
  * @return null|string
  */
 private function readMercurial()
 {
     $hgDir = Path::combine($this->repositoryRoot, '.hg');
     if (!is_dir($hgDir) || !OS::hasBinary('hg')) {
         return null;
     }
     $hg = Exec::create('hg', '--repository', $this->repositoryRoot);
     // Removes everything but the tag if distance is zero.
     $hg->run('log', '-r', '.', '--template', '{latesttag}{sub(\'^-0-m.*\', \'\', \'-{latesttagdistance}-m{node|short}\')}');
     $tag = Dot::get($hg->getOutput(), 0);
     // Actual null if no lines were returned or `hg log` returned actual "null".
     // Either way, need to fall back to the revision id.
     if ($tag === null || $tag === 'null' || Strings::startsWith($tag, 'null-')) {
         $hg->run('id', '-i');
         $tag = Dot::get($hg->getOutput(), 0);
         // Remove 'dirty' plus from revision id
         $tag = rtrim($tag, '+');
     }
     $summary = $hg->run('summary')->getOutput();
     $isDirty = 0 === count(array_filter($summary, function ($line) {
         return preg_match('/^commit: .*\\(clean\\)$/', $line) === 1;
     }));
     if ($isDirty) {
         $tag .= '-dirty';
     }
     return $tag;
 }
Exemple #14
0
 /**
  * startsWith() をテストします. 以下を確認します.
  * 
  * - 第 1 引数の文字列の先頭が第 2 引数の文字列に合致した場合に true, それ以外は false を返す
  * - 第 2 引数が空文字列の場合は true を返す
  * - 引数が文字列型でない場合は文字列に変換してから適用する
  * 
  * @covers Peach\Util\Strings::startsWith
  */
 public function testStartsWith()
 {
     $this->assertSame(true, Strings::startsWith("The quick brown fox", "The"));
     $this->assertSame(false, Strings::startsWith("Hogehoge", "hoge"));
     $this->assertSame(true, Strings::startsWith("something", ""));
     $prefix = new StringsTest_Object("TEST");
     $subject = new StringsTest_Object("TEST object");
     $other = new StringsTest_Object("fuga");
     $this->assertSame(true, Strings::startsWith($subject, $prefix));
     $this->assertSame(false, Strings::startsWith($subject, $other));
 }
 public static function startsWith($prefix)
 {
     return function ($string) use($prefix) {
         return Strings::startsWith($string, $prefix);
     };
 }
Exemple #16
0
 /**
  * Generates code for {macro ...} to the output.
  * @param  string
  * @param  string
  * @param  string
  * @param  bool
  * @return MacroNode
  */
 public function writeMacro($name, $args = NULL, $modifiers = NULL, $isRightmost = FALSE, HtmlNode $htmlNode = NULL, $prefix = NULL)
 {
     if ($name[0] === '/') {
         // closing
         $node = end($this->macroNodes);
         if (!$node || "/{$node->name}" !== $name && '/' !== $name || $modifiers || $args && $node->args && !Strings::startsWith("{$node->args} ", "{$args} ")) {
             $name .= $args ? ' ' : '';
             throw new CompileException("Unexpected macro {{$name}{$args}{$modifiers}}" . ($node ? ", expecting {/{$node->name}}" . ($args && $node->args ? " or eventually {/{$node->name} {$node->args}}" : '') : ''));
         }
         array_pop($this->macroNodes);
         if (!$node->args) {
             $node->setArgs($args);
         }
         $isLeftmost = $node->content ? trim(substr($this->output, strrpos("\n{$this->output}", "\n"))) === '' : FALSE;
         $node->closing = TRUE;
         $node->macro->nodeClosed($node);
         $this->output =& $node->saved[0];
         $this->writeCode($node->openingCode, $this->output, $node->saved[1]);
         $this->writeCode($node->closingCode, $node->content, $isRightmost, $isLeftmost);
         $this->output .= $node->content;
     } else {
         // opening
         $node = $this->expandMacro($name, $args, $modifiers, $htmlNode, $prefix);
         if ($node->isEmpty) {
             $this->writeCode($node->openingCode, $this->output, $isRightmost);
         } else {
             $this->macroNodes[] = $node;
             $node->saved = array(&$this->output, $isRightmost);
             $this->output =& $node->content;
         }
     }
     return $node;
 }