toolkit/mozapps/update/common/readstrings.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include <limits.h>
     8 #include <string.h>
     9 #include <stdio.h>
    10 #include "readstrings.h"
    11 #include "errors.h"
    13 #ifdef XP_WIN
    14 # define NS_tfopen _wfopen
    15 # define OPEN_MODE L"rb"
    16 #else
    17 # define NS_tfopen fopen
    18 # define OPEN_MODE "r"
    19 #endif
    21 // stack based FILE wrapper to ensure that fclose is called.
    22 class AutoFILE {
    23 public:
    24   AutoFILE(FILE *fp) : fp_(fp) {}
    25   ~AutoFILE() { if (fp_) fclose(fp_); }
    26   operator FILE *() { return fp_; }
    27 private:
    28   FILE *fp_;
    29 };
    31 class AutoCharArray {
    32 public:
    33   AutoCharArray(size_t len) { ptr_ = new char[len]; }
    34   ~AutoCharArray() { delete[] ptr_; }
    35   operator char *() { return ptr_; }
    36 private:
    37   char *ptr_;
    38 };
    40 static const char kNL[] = "\r\n";
    41 static const char kEquals[] = "=";
    42 static const char kWhitespace[] = " \t";
    43 static const char kRBracket[] = "]";
    45 static const char*
    46 NS_strspnp(const char *delims, const char *str)
    47 {
    48   const char *d;
    49   do {
    50     for (d = delims; *d != '\0'; ++d) {
    51       if (*str == *d) {
    52         ++str;
    53         break;
    54       }
    55     }
    56   } while (*d);
    58   return str;
    59 }
    61 static char*
    62 NS_strtok(const char *delims, char **str)
    63 {
    64   if (!*str)
    65     return nullptr;
    67   char *ret = (char*) NS_strspnp(delims, *str);
    69   if (!*ret) {
    70     *str = ret;
    71     return nullptr;
    72   }
    74   char *i = ret;
    75   do {
    76     for (const char *d = delims; *d != '\0'; ++d) {
    77       if (*i == *d) {
    78         *i = '\0';
    79         *str = ++i;
    80         return ret;
    81       }
    82     }
    83     ++i;
    84   } while (*i);
    86   *str = nullptr;
    87   return ret;
    88 }
    90 /**
    91  * Find a key in a keyList containing zero-delimited keys ending with "\0\0".
    92  * Returns a zero-based index of the key in the list, or -1 if the key is not found.
    93  */
    94 static int
    95 find_key(const char *keyList, char* key)
    96 {
    97   if (!keyList)
    98     return -1;
   100   int index = 0;
   101   const char *p = keyList;
   102   while (*p)
   103   {
   104     if (strcmp(key, p) == 0)
   105       return index;
   107     p += strlen(p) + 1;
   108     index++;
   109   }
   111   // The key was not found if we came here
   112   return -1;
   113 }
   115 /**
   116  * A very basic parser for updater.ini taken mostly from nsINIParser.cpp
   117  * that can be used by standalone apps.
   118  *
   119  * @param path       Path to the .ini file to read
   120  * @param keyList    List of zero-delimited keys ending with two zero characters
   121  * @param numStrings Number of strings to read into results buffer - must be equal to the number of keys
   122  * @param results    Two-dimensional array of strings to be filled in the same order as the keys provided
   123  * @param section    Optional name of the section to read; defaults to "Strings"
   124  */
   125 int
   126 ReadStrings(const NS_tchar *path,
   127             const char *keyList,
   128             unsigned int numStrings,
   129             char results[][MAX_TEXT_LEN],
   130             const char *section)
   131 {
   132   AutoFILE fp = NS_tfopen(path, OPEN_MODE);
   134   if (!fp)
   135     return READ_ERROR;
   137   /* get file size */
   138   if (fseek(fp, 0, SEEK_END) != 0)
   139     return READ_ERROR;
   141   long len = ftell(fp);
   142   if (len <= 0)
   143     return READ_ERROR;
   145   size_t flen = size_t(len);
   146   AutoCharArray fileContents(flen + 1);
   147   if (!fileContents)
   148     return READ_STRINGS_MEM_ERROR;
   150   /* read the file in one swoop */
   151   if (fseek(fp, 0, SEEK_SET) != 0)
   152     return READ_ERROR;
   154   size_t rd = fread(fileContents, sizeof(char), flen, fp);
   155   if (rd != flen)
   156     return READ_ERROR;
   158   fileContents[flen] = '\0';
   160   char *buffer = fileContents;
   161   bool inStringsSection = false;
   163   unsigned int read = 0;
   165   while (char *token = NS_strtok(kNL, &buffer)) {
   166     if (token[0] == '#' || token[0] == ';') // it's a comment
   167       continue;
   169     token = (char*) NS_strspnp(kWhitespace, token);
   170     if (!*token) // empty line
   171       continue;
   173     if (token[0] == '[') { // section header!
   174       ++token;
   175       char const * currSection = token;
   177       char *rb = NS_strtok(kRBracket, &token);
   178       if (!rb || NS_strtok(kWhitespace, &token)) {
   179         // there's either an unclosed [Section or a [Section]Moretext!
   180         // we could frankly decide that this INI file is malformed right
   181         // here and stop, but we won't... keep going, looking for
   182         // a well-formed [section] to continue working with
   183         inStringsSection = false;
   184       }
   185       else {
   186         if (section)
   187           inStringsSection = strcmp(currSection, section) == 0;
   188         else
   189           inStringsSection = strcmp(currSection, "Strings") == 0;
   190       }
   192       continue;
   193     }
   195     if (!inStringsSection) {
   196       // If we haven't found a section header (or we found a malformed
   197       // section header), or this isn't the [Strings] section don't bother
   198       // parsing this line.
   199       continue;
   200     }
   202     char *key = token;
   203     char *e = NS_strtok(kEquals, &token);
   204     if (!e)
   205       continue;
   207     int keyIndex = find_key(keyList, key);
   208     if (keyIndex >= 0 && (unsigned int)keyIndex < numStrings)
   209     {
   210       strncpy(results[keyIndex], token, MAX_TEXT_LEN - 1);
   211       results[keyIndex][MAX_TEXT_LEN - 1] = '\0';
   212       read++;
   213     }
   214   }
   216   return (read == numStrings) ? OK : PARSE_ERROR;
   217 }
   219 // A wrapper function to read strings for the updater.
   220 // Added for compatibility with the original code.
   221 int
   222 ReadStrings(const NS_tchar *path, StringTable *results)
   223 {
   224   const unsigned int kNumStrings = 2;
   225   const char *kUpdaterKeys = "Title\0Info\0";
   226   char updater_strings[kNumStrings][MAX_TEXT_LEN];
   228   int result = ReadStrings(path, kUpdaterKeys, kNumStrings, updater_strings);
   230   strncpy(results->title, updater_strings[0], MAX_TEXT_LEN - 1);
   231   results->title[MAX_TEXT_LEN - 1] = '\0';
   232   strncpy(results->info, updater_strings[1], MAX_TEXT_LEN - 1);
   233   results->info[MAX_TEXT_LEN - 1] = '\0';
   235   return result;
   236 }

mercurial