LCOV - code coverage report
Current view: directory - toolkit/mozapps/update/common - readstrings.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 100 88 88.0 %
Date: 2012-06-02 Functions: 11 11 100.0 %

       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                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is Google Inc.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Darin Fisher <darin@meer.net>
      24                 :  *  Alex Pakhotin <alexp@mozilla.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include <limits.h>
      41                 : #include <string.h>
      42                 : #include <stdio.h>
      43                 : #include "readstrings.h"
      44                 : #include "errors.h"
      45                 : 
      46                 : #ifdef XP_WIN
      47                 : # define NS_tfopen _wfopen
      48                 : # define OPEN_MODE L"rb"
      49                 : #else
      50                 : # define NS_tfopen fopen
      51                 : # define OPEN_MODE "r"
      52                 : #endif
      53                 : 
      54                 : // stack based FILE wrapper to ensure that fclose is called.
      55                 : class AutoFILE {
      56                 : public:
      57               5 :   AutoFILE(FILE *fp) : fp_(fp) {}
      58               5 :   ~AutoFILE() { if (fp_) fclose(fp_); }
      59              21 :   operator FILE *() { return fp_; }
      60                 : private:
      61                 :   FILE *fp_;
      62                 : };
      63                 : 
      64                 : class AutoCharArray {
      65                 : public:
      66               4 :   AutoCharArray(size_t len) { ptr_ = new char[len]; }
      67               4 :   ~AutoCharArray() { delete[] ptr_; }
      68              16 :   operator char *() { return ptr_; }
      69                 : private:
      70                 :   char *ptr_;
      71                 : };
      72                 : 
      73                 : static const char kNL[] = "\r\n";
      74                 : static const char kEquals[] = "=";
      75                 : static const char kWhitespace[] = " \t";
      76                 : static const char kRBracket[] = "]";
      77                 : 
      78                 : static const char*
      79             247 : NS_strspnp(const char *delims, const char *str)
      80                 : {
      81                 :   const char *d;
      82             247 :   do {
      83             636 :     for (d = delims; *d != '\0'; ++d) {
      84             469 :       if (*str == *d) {
      85              80 :         ++str;
      86              80 :         break;
      87                 :       }
      88                 :     }
      89                 :   } while (*d);
      90                 : 
      91             167 :   return str;
      92                 : }
      93                 : 
      94                 : static char*
      95             125 : NS_strtok(const char *delims, char **str)
      96                 : {
      97             125 :   if (!*str)
      98               0 :     return NULL;
      99                 : 
     100             125 :   char *ret = (char*) NS_strspnp(delims, *str);
     101                 : 
     102             125 :   if (!*ret) {
     103              16 :     *str = ret;
     104              16 :     return NULL;
     105                 :   }
     106                 : 
     107             109 :   char *i = ret;
     108            1396 :   do {
     109            4180 :     for (const char *d = delims; *d != '\0'; ++d) {
     110            2784 :       if (*i == *d) {
     111             109 :         *i = '\0';
     112             109 :         *str = ++i;
     113             109 :         return ret;
     114                 :       }
     115                 :     }
     116            1396 :     ++i;
     117                 :   } while (*i);
     118                 : 
     119               0 :   *str = NULL;
     120               0 :   return ret;
     121                 : }
     122                 : 
     123                 : /**
     124                 :  * Find a key in a keyList containing zero-delimited keys ending with "\0\0".
     125                 :  * Returns a zero-based index of the key in the list, or -1 if the key is not found.
     126                 :  */
     127                 : static int
     128              13 : find_key(const char *keyList, char* key)
     129                 : {
     130              13 :   if (!keyList)
     131               0 :     return -1;
     132                 : 
     133              13 :   int index = 0;
     134              13 :   const char *p = keyList;
     135              43 :   while (*p)
     136                 :   {
     137              22 :     if (strcmp(key, p) == 0)
     138               5 :       return index;
     139                 : 
     140              17 :     p += strlen(p) + 1;
     141              17 :     index++;
     142                 :   }
     143                 : 
     144                 :   // The key was not found if we came here
     145               8 :   return -1;
     146                 : }
     147                 : 
     148                 : /**
     149                 :  * A very basic parser for updater.ini taken mostly from nsINIParser.cpp
     150                 :  * that can be used by standalone apps.
     151                 :  *
     152                 :  * @param path       Path to the .ini file to read
     153                 :  * @param keyList    List of zero-delimited keys ending with two zero characters
     154                 :  * @param numStrings Number of strings to read into results buffer - must be equal to the number of keys
     155                 :  * @param results    Two-dimensional array of strings to be filled in the same order as the keys provided
     156                 :  * @param section    Optional name of the section to read; defaults to "Strings"
     157                 :  */
     158                 : int
     159               5 : ReadStrings(const NS_tchar *path,
     160                 :             const char *keyList,
     161                 :             unsigned int numStrings,
     162                 :             char results[][MAX_TEXT_LEN],
     163                 :             const char *section)
     164                 : {
     165              10 :   AutoFILE fp = NS_tfopen(path, OPEN_MODE);
     166                 : 
     167               5 :   if (!fp)
     168               1 :     return READ_ERROR;
     169                 : 
     170                 :   /* get file size */
     171               4 :   if (fseek(fp, 0, SEEK_END) != 0)
     172               0 :     return READ_ERROR;
     173                 : 
     174               4 :   long len = ftell(fp);
     175               4 :   if (len <= 0)
     176               0 :     return READ_ERROR;
     177                 : 
     178               4 :   size_t flen = size_t(len);
     179               8 :   AutoCharArray fileContents(flen + 1);
     180               4 :   if (!fileContents)
     181               0 :     return READ_STRINGS_MEM_ERROR;
     182                 : 
     183                 :   /* read the file in one swoop */
     184               4 :   if (fseek(fp, 0, SEEK_SET) != 0)
     185               0 :     return READ_ERROR;
     186                 : 
     187               4 :   size_t rd = fread(fileContents, sizeof(char), flen, fp);
     188               4 :   if (rd != flen)
     189               0 :     return READ_ERROR;
     190                 : 
     191               4 :   fileContents[flen] = '\0';
     192                 : 
     193               4 :   char *buffer = fileContents;
     194               4 :   bool inStringsSection = false;
     195                 : 
     196               4 :   unsigned int read = 0;
     197                 : 
     198             172 :   while (char *token = NS_strtok(kNL, &buffer)) {
     199              84 :     if (token[0] == '#' || token[0] == ';') // it's a comment
     200              42 :       continue;
     201                 : 
     202              42 :     token = (char*) NS_strspnp(kWhitespace, token);
     203              42 :     if (!*token) // empty line
     204               0 :       continue;
     205                 : 
     206              42 :     if (token[0] == '[') { // section header!
     207              12 :       ++token;
     208              12 :       char const * currSection = token;
     209                 : 
     210              12 :       char *rb = NS_strtok(kRBracket, &token);
     211              12 :       if (!rb || NS_strtok(kWhitespace, &token)) {
     212                 :         // there's either an unclosed [Section or a [Section]Moretext!
     213                 :         // we could frankly decide that this INI file is malformed right
     214                 :         // here and stop, but we won't... keep going, looking for
     215                 :         // a well-formed [section] to continue working with
     216               0 :         inStringsSection = false;
     217                 :       }
     218                 :       else {
     219              12 :         if (section)
     220               3 :           inStringsSection = strcmp(currSection, section) == 0;
     221                 :         else
     222               9 :           inStringsSection = strcmp(currSection, "Strings") == 0;
     223                 :       }
     224                 : 
     225              12 :       continue;
     226                 :     }
     227                 : 
     228              30 :     if (!inStringsSection) {
     229                 :       // If we haven't found a section header (or we found a malformed
     230                 :       // section header), or this isn't the [Strings] section don't bother
     231                 :       // parsing this line.
     232              17 :       continue;
     233                 :     }
     234                 : 
     235              13 :     char *key = token;
     236              13 :     char *e = NS_strtok(kEquals, &token);
     237              13 :     if (!e)
     238               0 :       continue;
     239                 : 
     240              13 :     int keyIndex = find_key(keyList, key);
     241              13 :     if (keyIndex >= 0 && (unsigned int)keyIndex < numStrings)
     242                 :     {
     243               5 :       strncpy(results[keyIndex], token, MAX_TEXT_LEN - 1);
     244               5 :       results[keyIndex][MAX_TEXT_LEN - 1] = '\0';
     245               5 :       read++;
     246                 :     }
     247                 :   }
     248                 : 
     249               6 :   return (read == numStrings) ? OK : PARSE_ERROR;
     250                 : }
     251                 : 
     252                 : // A wrapper function to read strings for the updater.
     253                 : // Added for compatibility with the original code.
     254                 : int
     255               4 : ReadStrings(const NS_tchar *path, StringTable *results)
     256                 : {
     257               4 :   const unsigned int kNumStrings = 2;
     258               4 :   const char *kUpdaterKeys = "Title\0Info\0";
     259                 :   char updater_strings[kNumStrings][MAX_TEXT_LEN];
     260                 : 
     261               4 :   int result = ReadStrings(path, kUpdaterKeys, kNumStrings, updater_strings);
     262                 : 
     263               4 :   strncpy(results->title, updater_strings[0], MAX_TEXT_LEN - 1);
     264               4 :   results->title[MAX_TEXT_LEN - 1] = '\0';
     265               4 :   strncpy(results->info, updater_strings[1], MAX_TEXT_LEN - 1);
     266               4 :   results->info[MAX_TEXT_LEN - 1] = '\0';
     267                 : 
     268               4 :   return result;
     269                 : }

Generated by: LCOV version 1.7