LibreOffice Module onlineupdate (master) 1
readstrings.cxx
Go to the documentation of this file.
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/. */
6
7#include <limits.h>
8#include <string.h>
9#include <stdio.h>
10#include "readstrings.h"
11#include "errors.h"
12
13#ifdef _WIN32
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
20
21// stack based FILE wrapper to ensure that fclose is called.
23{
24public:
25 explicit AutoFILE(FILE *fp) : fp_(fp) {}
27 {
28 if (fp_) fclose(fp_);
29 }
30 operator FILE *()
31 {
32 return fp_;
33 }
34private:
36};
37
39{
40public:
41 explicit AutoCharArray(size_t len)
42 {
43 ptr_ = new char[len];
44 }
46 {
47 delete[] ptr_;
48 }
49 operator char *()
50 {
51 return ptr_;
52 }
53private:
54 char *ptr_;
55};
56
57static const char kNL[] = "\r\n";
58static const char kEquals[] = "=";
59static const char kWhitespace[] = " \t";
60static const char kRBracket[] = "]";
61
62static const char*
63NS_strspnp(const char *delims, const char *str)
64{
65 const char *d;
66 do
67 {
68 for (d = delims; *d != '\0'; ++d)
69 {
70 if (*str == *d)
71 {
72 ++str;
73 break;
74 }
75 }
76 }
77 while (*d);
78
79 return str;
80}
81
82static char*
83NS_strtok(const char *delims, char **str)
84{
85 if (!*str)
86 return nullptr;
87
88 char *ret = (char*) NS_strspnp(delims, *str);
89
90 if (!*ret)
91 {
92 *str = ret;
93 return nullptr;
94 }
95
96 char *i = ret;
97 do
98 {
99 for (const char *d = delims; *d != '\0'; ++d)
100 {
101 if (*i == *d)
102 {
103 *i = '\0';
104 *str = ++i;
105 return ret;
106 }
107 }
108 ++i;
109 }
110 while (*i);
111
112 *str = nullptr;
113 return ret;
114}
115
120static int
121find_key(const char *keyList, char* key)
122{
123 if (!keyList)
124 return -1;
125
126 int index = 0;
127 const char *p = keyList;
128 while (*p)
129 {
130 if (strcmp(key, p) == 0)
131 return index;
132
133 p += strlen(p) + 1;
134 index++;
135 }
136
137 // The key was not found if we came here
138 return -1;
139}
140
151int
153 const char *keyList,
154 unsigned int numStrings,
155 char results[][MAX_TEXT_LEN],
156 const char *section)
157{
158 AutoFILE fp(NS_tfopen(path, OPEN_MODE));
159
160 if (!fp)
161 return READ_ERROR;
162
163 /* get file size */
164 if (fseek(fp, 0, SEEK_END) != 0)
165 return READ_ERROR;
166
167 long len = ftell(fp);
168 if (len <= 0)
169 return READ_ERROR;
170
171 size_t flen = size_t(len);
172 AutoCharArray fileContents(flen + 1);
173 if (!fileContents)
175
176 /* read the file in one swoop */
177 if (fseek(fp, 0, SEEK_SET) != 0)
178 return READ_ERROR;
179
180 size_t rd = fread(fileContents, sizeof(char), flen, fp);
181 if (rd != flen)
182 return READ_ERROR;
183
184 fileContents[flen] = '\0';
185
186 char *buffer = fileContents;
187 bool inStringsSection = false;
188
189 unsigned int read = 0;
190
191 while (char *token = NS_strtok(kNL, &buffer))
192 {
193 if (token[0] == '#' || token[0] == ';') // it's a comment
194 continue;
195
196 token = (char*) NS_strspnp(kWhitespace, token);
197 if (!*token) // empty line
198 continue;
199
200 if (token[0] == '[') // section header!
201 {
202 ++token;
203 char const * currSection = token;
204
205 char *rb = NS_strtok(kRBracket, &token);
206 if (!rb || NS_strtok(kWhitespace, &token))
207 {
208 // there's either an unclosed [Section or a [Section]Moretext!
209 // we could frankly decide that this INI file is malformed right
210 // here and stop, but we won't... keep going, looking for
211 // a well-formed [section] to continue working with
212 inStringsSection = false;
213 }
214 else
215 {
216 if (section)
217 inStringsSection = strcmp(currSection, section) == 0;
218 else
219 inStringsSection = strcmp(currSection, "Strings") == 0;
220 }
221
222 continue;
223 }
224
225 if (!inStringsSection)
226 {
227 // If we haven't found a section header (or we found a malformed
228 // section header), or this isn't the [Strings] section don't bother
229 // parsing this line.
230 continue;
231 }
232
233 char *key = token;
234 char *e = NS_strtok(kEquals, &token);
235 if (!e)
236 continue;
237
238 int keyIndex = find_key(keyList, key);
239 if (keyIndex >= 0 && (unsigned int)keyIndex < numStrings)
240 {
241 strncpy(results[keyIndex], token, MAX_TEXT_LEN - 1);
242 results[keyIndex][MAX_TEXT_LEN - 1] = '\0';
243 read++;
244 }
245 }
246
247 return (read == numStrings) ? OK : PARSE_ERROR;
248}
249
250// A wrapper function to read strings for the updater.
251// Added for compatibility with the original code.
252int
253ReadStrings(const NS_tchar *path, StringTable *results)
254{
255 const unsigned int kNumStrings = 2;
256 const char *kUpdaterKeys = "Title\0Info\0";
257 char updater_strings[kNumStrings][MAX_TEXT_LEN];
258
259 int result = ReadStrings(path, kUpdaterKeys, kNumStrings, updater_strings);
260
261 strncpy(results->title, updater_strings[0], MAX_TEXT_LEN - 1);
262 results->title[MAX_TEXT_LEN - 1] = '\0';
263 strncpy(results->info, updater_strings[1], MAX_TEXT_LEN - 1);
264 results->info[MAX_TEXT_LEN - 1] = '\0';
265
266 return result;
267}
double d
AutoCharArray(size_t len)
Definition: readstrings.cxx:41
AutoFILE(FILE *fp)
Definition: readstrings.cxx:25
FILE * fp_
Definition: readstrings.cxx:35
#define PARSE_ERROR
Definition: errors.h:22
#define READ_STRINGS_MEM_ERROR
Definition: errors.h:27
#define OK
Definition: errors.h:10
#define READ_ERROR
Definition: errors.h:23
void * p
@ section
int i
index
static const char * NS_strspnp(const char *delims, const char *str)
Definition: readstrings.cxx:63
static const char kWhitespace[]
Definition: readstrings.cxx:59
static const char kRBracket[]
Definition: readstrings.cxx:60
static const char kNL[]
Definition: readstrings.cxx:57
static char * NS_strtok(const char *delims, char **str)
Definition: readstrings.cxx:83
#define OPEN_MODE
Definition: readstrings.cxx:18
static const char kEquals[]
Definition: readstrings.cxx:58
static int find_key(const char *keyList, char *key)
Find a key in a keyList containing zero-delimited keys ending with "\0\0".
#define NS_tfopen
Definition: readstrings.cxx:17
int ReadStrings(const NS_tchar *path, const char *keyList, unsigned int numStrings, char results[][MAX_TEXT_LEN], const char *section)
A very basic parser for updater.ini taken mostly from nsINIParser.cpp that can be used by standalone ...
#define MAX_TEXT_LEN
Definition: readstrings.h:10
char title[MAX_TEXT_LEN]
Definition: readstrings.h:20
char info[MAX_TEXT_LEN]
Definition: readstrings.h:21
char NS_tchar
Definition: types.hxx:20
Any result