• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

akrennmair / newsbeuter / 512

pending completion
512

push

travis-ci

Minoru
Fix OS X build by upgrading pkg-config if necessary

3743 of 13459 relevant lines covered (27.81%)

222.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.68
/src/utils.cpp
1
#include <utils.h>
2
#include <logger.h>
3
#include <config.h>
4

5
#include <sys/types.h>
6
#include <sys/stat.h>
7
#include <fcntl.h>
8
#include <iconv.h>
9
#include <errno.h>
10
#include <pwd.h>
11
#include <libgen.h>
12
#include <sys/utsname.h>
13

14
#include <unordered_set>
15
#include <unistd.h>
16
#include <sstream>
17
#include <locale>
18
#include <cwchar>
19
#include <cstring>
20
#include <cstdlib>
21
#include <cstdarg>
22

23
#include <curl/curl.h>
24

25
#include <langinfo.h>
26
#include <stfl.h>
27
#include <libxml/uri.h>
28

29
#if HAVE_GCRYPT
30
#include <gnutls/gnutls.h>
31
#include <gcrypt.h>
32
#include <errno.h>
33
#include <pthread.h>
34
GCRY_THREAD_OPTION_PTHREAD_IMPL;
35
#endif
36

37
#if HAVE_OPENSSL
38
#include <openssl/crypto.h>
39
#endif
40

41
namespace newsbeuter {
42

43
std::vector<std::string> utils::tokenize_quoted(const std::string& str, std::string delimiters) {
280 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
44
        /*
45
         * This function tokenizes strings, obeying quotes and throwing away comments that start
46
         * with a '#'.
47
         *
48
         * e.g. line: foo bar "foo bar" "a test"
49
         * is parsed to 4 elements:
50
         *         [0]: foo
51
         *         [1]: bar
52
         *         [2]: foo bar
53
         *         [3]: a test
54
         *
55
         * e.g. line: yes great "x\ny" # comment
56
         * is parsed to 3 elements:
57
         *         [0]: yes
58
         *         [1]: great
59
         *         [2]: x
60
         *         y
61
         *
62
         *         \", \r, \n, \t and \v are replaced with the literals that you know from C/C++ strings.
63
         *
64
         */
65
        bool attach_backslash = true;
420✔
66
        std::vector<std::string> tokens;
420✔
67
        std::string::size_type last_pos = str.find_first_not_of(delimiters, 0);
420✔
68
        std::string::size_type pos = last_pos;
424✔
69

70
        while (pos != std::string::npos && last_pos != std::string::npos) {
3,617✔
71
                if (str[last_pos] == '#') // stop as soon as we found a comment
1,512✔
72
                        break;
96✔
73

74
                if (str[last_pos] == '"') {
1,384✔
75
                        ++last_pos;
174✔
76
                        pos = last_pos;
174✔
77
                        int backslash_count = 0;
174✔
78
                        while (pos < str.length() && (str[pos] != '"' || (backslash_count%2))) {
3,051✔
79
                                if (str[pos] == '\\') {
1,136✔
80
                                        ++backslash_count;
162✔
81
                                } else {
108 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
82
                                        backslash_count = 0;
690✔
83
                                }
84
                                ++pos;
852✔
85
                        }
284 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
86
                        if (pos >= str.length()) {
174✔
87
                                pos = std::string::npos;
18✔
88
                                std::string token;
21✔
89
                                while (last_pos < str.length()) {
141✔
90
                                        if (str[last_pos] == '\\') {
96✔
91
                                                if (str[last_pos-1] == '\\') {
96✔
92
                                                        if (attach_backslash) {
54✔
93
                                                                token.append("\\");
36✔
94
                                                        }
24 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
95
                                                        attach_backslash = !attach_backslash;
54✔
96
                                                }
36 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
97
                                        } else {
48 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
98
                                                if (str[last_pos-1] == '\\') {
×
99
                                                        append_escapes(token, str[last_pos]);
×
100
                                                } else {
×
101
                                                        token.append(1, str[last_pos]);
×
102
                                                }
103
                                        }
104
                                        ++last_pos;
72✔
105
                                }
24 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
106
                                tokens.push_back(token);
18✔
107
                        } else {
12 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
108
                                std::string token;
182✔
109
                                while (last_pos < pos) {
1,456✔
110
                                        if (str[last_pos] == '\\') {
1,040✔
111
                                                if (str[last_pos-1] == '\\') {
120✔
112
                                                        if (attach_backslash) {
54✔
113
                                                                token.append("\\");
36✔
114
                                                        }
24 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
115
                                                        attach_backslash = !attach_backslash;
54✔
116
                                                }
36 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
117
                                        } else {
60 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
118
                                                if (str[last_pos-1] == '\\') {
920✔
119
                                                        append_escapes(token, str[last_pos]);
32✔
120
                                                } else {
16 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
121
                                                        token.append(1, str[last_pos]);
888✔
122
                                                }
123
                                        }
124
                                        ++last_pos;
780✔
125
                                }
260 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
126
                                tokens.push_back(token);
156✔
127
                                ++pos;
156✔
128
                        }
104 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
129
                } else {
116 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
130
                        pos = str.find_first_of(delimiters, last_pos);
864✔
131
                        tokens.push_back(str.substr(last_pos, pos - last_pos));
2,016✔
132
                }
133
                last_pos = str.find_first_not_of(delimiters, pos);
1,038✔
134
        }
346 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
135

136
        return tokens;
420✔
137
}
560 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
138

139

140
std::vector<std::string> utils::tokenize(const std::string& str, std::string delimiters) {
92 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
141
        /*
142
         * This function tokenizes a string by the delimiters. Plain and simple.
143
         */
144
        std::vector<std::string> tokens;
138✔
145
        std::string::size_type last_pos = str.find_first_not_of(delimiters, 0);
138✔
146
        std::string::size_type pos = str.find_first_of(delimiters, last_pos);
138✔
147

148
        while (std::string::npos != pos || std::string::npos != last_pos) {
1,375✔
149
                tokens.push_back(str.substr(last_pos, pos - last_pos));
924✔
150
                last_pos = str.find_first_not_of(delimiters, pos);
396✔
151
                pos = str.find_first_of(delimiters, last_pos);
396✔
152
        }
132 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
153
        return tokens;
138✔
154
}
184 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
155

156
std::vector<std::wstring> utils::wtokenize(const std::wstring& str, std::wstring delimiters) {
60 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
157
        /*
158
         * This function tokenizes a string by the delimiters. Plain and simple.
159
         */
160
        std::vector<std::wstring> tokens;
90✔
161
        std::wstring::size_type last_pos = str.find_first_not_of(delimiters, 0);
90✔
162
        std::wstring::size_type pos = str.find_first_of(delimiters, last_pos);
90✔
163

164
        while (std::string::npos != pos || std::string::npos != last_pos) {
657✔
165
                tokens.push_back(str.substr(last_pos, pos - last_pos));
336✔
166
                last_pos = str.find_first_not_of(delimiters, pos);
144✔
167
                pos = str.find_first_of(delimiters, last_pos);
144✔
168
        }
48 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
169
        return tokens;
90✔
170
}
120 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
171

172
std::vector<std::string> utils::tokenize_spaced(const std::string& str, std::string delimiters) {
32 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
173
        std::vector<std::string> tokens;
48✔
174
        std::string::size_type last_pos = str.find_first_not_of(delimiters, 0);
48✔
175
        std::string::size_type pos = str.find_first_of(delimiters, last_pos);
48✔
176

177
        if (last_pos != 0) {
48✔
178
                tokens.push_back(std::string(" "));
14✔
179
        }
4 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
180

181
        while (std::string::npos != pos || std::string::npos != last_pos) {
544✔
182
                tokens.push_back(str.substr(last_pos, pos - last_pos));
392✔
183
                last_pos = str.find_first_not_of(delimiters, pos);
168✔
184
                if (last_pos > pos)
168✔
185
                        tokens.push_back(std::string(" "));
294✔
186
                pos = str.find_first_of(delimiters, last_pos);
168✔
187
        }
56 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
188

189
        return tokens;
48✔
190
}
64 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
191

192
std::vector<std::string> utils::tokenize_nl(const std::string& str, std::string delimiters) {
32 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
193
        std::vector<std::string> tokens;
48✔
194
        std::string::size_type last_pos = str.find_first_not_of(delimiters, 0);
48✔
195
        std::string::size_type pos = str.find_first_of(delimiters, last_pos);
48✔
196
        unsigned int i;
16 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
197

198
        LOG(LOG_DEBUG,"utils::tokenize_nl: last_pos = %u",last_pos);
176✔
199
        if (last_pos != std::string::npos) {
48✔
200
                for (i=0; i<last_pos; ++i) {
80✔
201
                        tokens.push_back(std::string("\n"));
×
202
                }
×
203
        }
32 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
204

205
        while (std::string::npos != pos || std::string::npos != last_pos) {
348✔
206
                tokens.push_back(str.substr(last_pos, pos - last_pos));
224✔
207
                LOG(LOG_DEBUG,"utils::tokenize_nl: substr = %s", str.substr(last_pos, pos - last_pos).c_str());
416✔
208
                last_pos = str.find_first_not_of(delimiters, pos);
96✔
209
                LOG(LOG_DEBUG,"utils::tokenize_nl: pos - last_pos = %u", last_pos - pos);
352✔
210
                for (i=0; last_pos != std::string::npos && pos != std::string::npos && i<(last_pos - pos); ++i) {
416✔
211
                        tokens.push_back(std::string("\n"));
112✔
212
                }
32 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
213
                pos = str.find_first_of(delimiters, last_pos);
96✔
214
        }
32 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
215

216
        return tokens;
48✔
217
}
72 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
218

219
void utils::remove_fs_lock(const std::string& lock_file) {
×
220
        LOG(LOG_DEBUG, "utils::remove_fs_lock: removed lockfile %s", lock_file.c_str());
×
221
        ::unlink(lock_file.c_str());
×
222
}
×
223

224
bool utils::try_fs_lock(const std::string& lock_file, pid_t & pid) {
×
225
        int fd;
×
226
        // pid == 0 indicates that something went majorly wrong during locking
227
        pid = 0;
×
228

229
        LOG(LOG_DEBUG, "utils::try_fs_lock: trying to lock %s", lock_file.c_str());
×
230

231
        // first, we open (and possibly create) the lock file
232
        fd = ::open(lock_file.c_str(), O_RDWR | O_CREAT, 0600);
×
233
        if (fd < 0)
×
234
                return false;
×
235

236
        // then we lock it (T_LOCK returns immediately if locking is not possible)
237
        if (lockf(fd, F_TLOCK, 0) == 0) {
×
238
                std::string pidtext = utils::to_string<unsigned int>(getpid());
×
239
                // locking successful -> truncate file and write own PID into it
240
                ftruncate(fd, 0);
×
241
                write(fd, pidtext.c_str(), pidtext.length());
×
242
                return true;
×
243
        }
×
244

245
        // locking was not successful -> read PID of locking process from it
246
        fd = ::open(lock_file.c_str(), O_RDONLY);
×
247
        if (fd >= 0) {
×
248
                char buf[32];
×
249
                int len = read(fd, buf, sizeof(buf)-1);
×
250
                unsigned int upid = 0;
×
251
                buf[len] = '\0';
×
252
                sscanf(buf, "%u", &upid);
×
253
                pid = upid;
×
254
                close(fd);
×
255
        }
×
256
        return false;
×
257
}
×
258

259

260
std::string utils::convert_text(const std::string& text, const std::string& tocode, const std::string& fromcode) {
532 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
261
        std::string result;
931✔
262

263
        if (strcasecmp(tocode.c_str(), fromcode.c_str())==0)
1,064✔
264
                return text;
1,330✔
265

266
        iconv_t cd = ::iconv_open((tocode + "//TRANSLIT").c_str(), fromcode.c_str());
×
267

268
        if (cd == reinterpret_cast<iconv_t>(-1))
×
269
                return result;
×
270

271
        size_t inbytesleft;
×
272
        size_t outbytesleft;
×
273

274
        /*
275
         * of all the Unix-like systems around there, only Linux/glibc seems to
276
         * come with a SuSv3-conforming iconv implementation.
277
         */
278
#if !(__linux) && !defined(__GLIBC__) && !defined(__APPLE__) && !defined(__OpenBSD__)
279
        const char * inbufp;
280
#else
281
        char * inbufp;
×
282
#endif
283
        char outbuf[16];
×
284
        char * outbufp = outbuf;
×
285

286
        outbytesleft = sizeof(outbuf);
×
287
        inbufp = const_cast<char *>(text.c_str()); // evil, but spares us some trouble
×
288
        inbytesleft = strlen(inbufp);
×
289

290
        do {
×
291
                char * old_outbufp = outbufp;
×
292
                int rc = ::iconv(cd, &inbufp, &inbytesleft, &outbufp, &outbytesleft);
×
293
                if (-1 == rc) {
×
294
                        switch (errno) {
×
295
                        case E2BIG:
296
                                result.append(old_outbufp, outbufp - old_outbufp);
×
297
                                outbufp = outbuf;
×
298
                                outbytesleft = sizeof(outbuf);
×
299
                                inbufp += strlen(inbufp) - inbytesleft;
×
300
                                inbytesleft = strlen(inbufp);
×
301
                                break;
×
302
                        case EILSEQ:
303
                        case EINVAL:
304
                                result.append(old_outbufp, outbufp - old_outbufp);
×
305
                                result.append("?");
×
306
                                inbufp += strlen(inbufp) - inbytesleft + 1;
×
307
                                inbytesleft = strlen(inbufp);
×
308
                                break;
×
309
                        default:
310
                                break;
×
311
                        }
312
                } else {
×
313
                        result.append(old_outbufp, outbufp - old_outbufp);
×
314
                }
315
        } while (inbytesleft > 0);
×
316

317
        iconv_close(cd);
×
318

319
        return result;
×
320
}
532 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
321

322
std::string utils::get_command_output(const std::string& cmd) {
28 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
323
        FILE * f = popen(cmd.c_str(), "r");
42✔
324
        std::string buf;
42✔
325
        char cbuf[1024];
14 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
326
        if (f) {
42✔
327
                size_t s;
14 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
328
                while ((s = fread(cbuf, 1, sizeof(cbuf), f)) > 0) {
157✔
329
                        buf.append(cbuf, s);
24✔
330
                }
8 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
331
                pclose(f);
42✔
332
        }
28 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
333
        return buf;
42✔
334
}
56 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
335

336
void utils::extract_filter(const std::string& line, std::string& filter, std::string& url) {
×
337
        std::string::size_type pos = line.find_first_of(":", 0);
×
338
        std::string::size_type pos1 = line.find_first_of(":", pos + 1);
×
339
        filter = line.substr(pos+1, pos1 - pos - 1);
×
340
        pos = pos1;
×
341
        url = line.substr(pos+1, line.length() - pos);
×
342
        LOG(LOG_DEBUG, "utils::extract_filter: %s -> filter: %s url: %s", line.c_str(), filter.c_str(), url.c_str());
×
343
}
×
344

345
static size_t my_write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
×
346
        std::string * pbuf = static_cast<std::string *>(userp);
×
347
        pbuf->append(static_cast<const char *>(buffer), size * nmemb);
×
348
        return size * nmemb;
×
349
}
350

351
std::string utils::retrieve_url(const std::string& url, configcontainer * cfgcont, const char * authinfo, const std::string* postdata) {
×
352
        std::string buf;
×
353

354
        CURL * easyhandle = curl_easy_init();
×
355
        set_common_curl_options(easyhandle, cfgcont);
×
356
        curl_easy_setopt(easyhandle, CURLOPT_URL, url.c_str());
×
357
        curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, my_write_data);
×
358
        curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &buf);
×
359

360
        if (postdata != NULL) {
×
361
                curl_easy_setopt(easyhandle, CURLOPT_POST, 1);
×
362
                curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, postdata->c_str());
×
363
        }
×
364

365
        if (authinfo) {
×
366
                curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, get_auth_method(cfgcont->get_configvalue("http-auth-method")));
×
367
                curl_easy_setopt(easyhandle, CURLOPT_USERPWD, authinfo);
×
368
        }
×
369

370
        curl_easy_perform(easyhandle);
×
371
        curl_easy_cleanup(easyhandle);
×
372

373
        if (postdata != NULL) {
×
374
                LOG(LOG_DEBUG, "utils::retrieve_url(%s)[%s]: %s", url.c_str(), postdata->c_str(), buf.c_str());
×
375
        } else {
×
376
                LOG(LOG_DEBUG, "utils::retrieve_url(%s)[-]: %s", url.c_str(), buf.c_str());
×
377
        }
378

379
        return buf;
×
380
}
×
381

382
void utils::run_command(const std::string& cmd, const std::string& input) {
×
383
        int rc = fork();
×
384
        switch (rc) {
×
385
        case -1:
386
                break;
×
387
        case 0: { // child:
388
                int fd = ::open("/dev/null", O_RDWR);
×
389
                close(0);
×
390
                close(1);
×
391
                close(2);
×
392
                dup2(fd, 0);
×
393
                dup2(fd, 1);
×
394
                dup2(fd, 2);
×
395
                LOG(LOG_DEBUG, "utils::run_command: %s '%s'", cmd.c_str(), input.c_str());
×
396
                execlp(cmd.c_str(), cmd.c_str(), input.c_str(), NULL);
×
397
                LOG(LOG_DEBUG, "utils::run_command: execlp of %s failed: %s", cmd.c_str(), strerror(errno));
×
398
                exit(1);
×
399
        }
400
        default:
401
                break;
×
402
        }
403
}
×
404

405
std::string utils::run_program(char * argv[], const std::string& input) {
8 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
406
        std::string buf;
12✔
407
        int ipipe[2];
4 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
408
        int opipe[2];
4 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
409
        pipe(ipipe);
12✔
410
        pipe(opipe);
12✔
411

412
        int rc = fork();
16✔
413
        switch (rc) {
12✔
414
        case -1:
415
                break;
×
416
        case 0: { // child:
417
                close(ipipe[1]);
×
418
                close(opipe[0]);
×
419
                dup2(ipipe[0], 0);
×
420
                dup2(opipe[1], 1);
×
421
                close(2);
×
422

423
                int errfd = ::open("/dev/null", O_WRONLY);
×
424
                if (errfd != -1) dup2(errfd, 2);
×
425

426
                execvp(argv[0], argv);
×
427
                exit(1);
×
428
        }
429
        default: {
430
                close(ipipe[0]);
12✔
431
                close(opipe[1]);
12✔
432
                write(ipipe[1], input.c_str(), input.length());
12✔
433
                close(ipipe[1]);
12✔
434
                char cbuf[1024];
4 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
435
                int rc2;
4 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
436
                while ((rc2 = read(opipe[0], cbuf, sizeof(cbuf))) > 0) {
56✔
437
                        buf.append(cbuf, rc2);
12✔
438
                }
4 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
439
                close(opipe[0]);
12✔
440
        }
441
        break;
12✔
442
        }
443
        return buf;
12✔
444
}
16 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
445

446
std::string utils::resolve_tilde(const std::string& str) {
8 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
447
        const char * homedir;
4 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
448
        std::string filepath;
12✔
449

450
        if (!(homedir = ::getenv("HOME"))) {
16✔
451
                struct passwd * spw = ::getpwuid(::getuid());
×
452
                if (spw) {
×
453
                        homedir = spw->pw_dir;
×
454
                } else {
×
455
                        homedir = "";
×
456
                }
457
        }
×
458

459
        if (strcmp(homedir,"")!=0) {
16✔
460
                if (str == "~") {
16✔
461
                        filepath.append(homedir);
×
462
                } else if (str.substr(0,2) == "~/") {
24✔
463
                        filepath.append(homedir);
6✔
464
                        filepath.append(1,'/');
6✔
465
                        filepath.append(str.substr(2,str.length()-2));
14✔
466
                } else {
4 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
467
                        filepath.append(str);
6✔
468
                }
469
        } else {
8 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
470
                filepath.append(str);
×
471
        }
472

473
        return filepath;
12✔
474
}
16 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
475

476
std::string utils::replace_all(std::string str, const std::string& from, const std::string& to) {
630 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
477
        std::string::size_type s = str.find(from);
630✔
478
        while (s != std::string::npos) {
1,281✔
479
                str.replace(s,from.length(), to);
84✔
480
                s = str.find(from, s + to.length());
84✔
481
        }
28 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
482
        return str;
630✔
483
}
484

485
std::wstring utils::utf8str2wstr(const std::string& utf8str) {
×
486
        stfl_ipool * pool = stfl_ipool_create("utf-8");
×
487
        std::wstring wstr = stfl_ipool_towc(pool, utf8str.c_str());
×
488
        stfl_ipool_destroy(pool);
×
489
        return wstr;
×
490
}
×
491

492
std::wstring utils::str2wstr(const std::string& str) {
980 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
493
        const char * codeset = nl_langinfo(CODESET);
1,470✔
494
        struct stfl_ipool * ipool = stfl_ipool_create(codeset);
1,470✔
495
        std::wstring result = stfl_ipool_towc(ipool, str.c_str());
1,960✔
496
        stfl_ipool_destroy(ipool);
1,470✔
497
        return result;
1,470✔
498
}
1,960 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
499

500
std::string utils::wstr2str(const std::wstring& wstr) {
260 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
501
        std::string codeset = nl_langinfo(CODESET);
585✔
502
        codeset.append("//TRANSLIT");
390✔
503
        struct stfl_ipool * ipool = stfl_ipool_create(codeset.c_str());
650✔
504
        std::string result = stfl_ipool_fromwc(ipool, wstr.c_str());
780✔
505
        stfl_ipool_destroy(ipool);
390✔
506
        return result;
455✔
507
}
520 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
508

509
template<class T> std::string utils::to_string(T var) {
12 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
510
        std::stringstream ret;
28✔
511
        ret << var;
24✔
512
        return ret.str();
28✔
513
}
16 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
514

515
// to avoid linker errors
516
template std::string utils::to_string<int>(int var);
517
template std::string utils::to_string<unsigned long>(unsigned long var);
518
template std::string utils::to_string<unsigned int>(unsigned int var);
519

520
std::string utils::absolute_url(const std::string& url, const std::string& link) {
140 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
521
        xmlChar * newurl = xmlBuildURI((const xmlChar *)link.c_str(), (const xmlChar *)url.c_str());
210✔
522
        std::string retval;
210✔
523
        if (newurl) {
210✔
524
                retval = (const char *)newurl;
210✔
525
                xmlFree(newurl);
210✔
526
        } else {
140 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
527
                retval = link;
×
528
        }
529
        return retval;
210✔
530
}
280 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
531

532
std::string utils::strprintf(const char * format, ...) {
760 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
533
        if (!format)
1,140✔
534
                return std::string();
6✔
535

536
        char buffer[1024];
378 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
537

538
        va_list ap;
378 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
539
        va_start(ap, format);
1,134✔
540

541
        unsigned int len = vsnprintf(buffer, sizeof(buffer), format, ap)+1;
1,134✔
542

543
        va_end(ap);
1,134✔
544
        if (len <= sizeof(buffer))
1,134✔
545
                return buffer;
1,512✔
546

547
        va_start(ap, format);
×
548

549
        char * buf = new char[len];
×
550
        vsnprintf(buf, len, format, ap);
×
551
        va_end(ap);
×
552

553
        std::string ret(buf);
×
554
        delete[] buf;
×
555

556
        return ret;
×
557
}
760 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
558

559
std::string utils::get_useragent(configcontainer * cfgcont) {
×
560
        std::string ua_pref = cfgcont->get_configvalue("user-agent");
×
561
        if (ua_pref.length() == 0) {
×
562
                struct utsname buf;
×
563
                uname(&buf);
×
564
                if (strcmp(buf.sysname, "Darwin") == 0) {
×
565
                        /* Assume it is a Mac from the last decade or at least Mac-like */
566
                        const char* PROCESSOR = "";
×
567
                        if (strcmp(buf.machine, "x86_64") == 0 || strcmp(buf.machine, "i386") == 0) {
×
568
                                PROCESSOR = "Intel ";
×
569
                        }
×
570
                        return utils::strprintf("%s/%s (Macintosh; %sMac OS X)", PROGRAM_NAME, PROGRAM_VERSION, PROCESSOR);
×
571
                }
572
                return utils::strprintf("%s/%s (%s %s)", PROGRAM_NAME, PROGRAM_VERSION, buf.sysname, buf.machine);
×
573
        }
574
        return ua_pref;
×
575
}
×
576

577
unsigned int utils::to_u(
78 only COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
578
                const std::string& str,
78 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
579
                const unsigned int default_value)
78 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
580
{
581
        std::istringstream is(str);
273✔
582
        unsigned int u;
78 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
583
        is >> u;
234✔
584
        if (is.fail() || ! is.eof()) {
686✔
585
                u = default_value;
12✔
586
        }
8 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
587
        return u;
273✔
588
}
156 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
589

590
scope_measure::scope_measure(const std::string& func, loglevel ll) : lvl(ll) {
360✔
591
        funcname = func;
270✔
592
        gettimeofday(&tv1, NULL);
270✔
593
}
360✔
594

595
void scope_measure::stopover(const std::string& son) {
×
596
        gettimeofday(&tv2, NULL);
×
597
        unsigned long diff = (((tv2.tv_sec - tv1.tv_sec) * 1000000) + tv2.tv_usec) - tv1.tv_usec;
×
598
        LOG(lvl, "scope_measure: function `%s' (stop over `%s') took %lu.%06lu s so far", funcname.c_str(), son.c_str(), diff / 1000000, diff % 1000000);
×
599
}
×
600

601
scope_measure::~scope_measure() {
270 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
602
        gettimeofday(&tv2, NULL);
270✔
603
        unsigned long diff = (((tv2.tv_sec - tv1.tv_sec) * 1000000) + tv2.tv_usec) - tv1.tv_usec;
270✔
604
        LOG(LOG_INFO, "scope_measure: function `%s' took %lu.%06lu s", funcname.c_str(), diff / 1000000, diff % 1000000);
990✔
605
}
405✔
606

607
void utils::append_escapes(std::string& str, char c) {
16 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
608
        switch (c) {
24✔
609
        case 'n':
610
                str.append("\n");
6✔
611
                break;
6✔
612
        case 'r':
613
                str.append("\r");
6✔
614
                break;
6✔
615
        case 't':
616
                str.append("\t");
6✔
617
                break;
6✔
618
        case '"':
619
                str.append("\"");
×
620
                break;
×
621
        case '\\':
622
                break;
×
623
        default:
624
                str.append(1, c);
6✔
625
                break;
6✔
626
        }
627
}
24✔
628

629
bool utils::is_valid_color(const std::string& color) {
84 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
630
        static const std::unordered_set<std::string> colors = {
165 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
631
                "black", "red", "green", "yellow", "blue",
5 only COMPILER=clang++-3.7 GCOV=/usr/bin/gcov ✔
632
                "magenta", "cyan", "white", "default"
4 only COMPILER=clang++-3.7 GCOV=/usr/bin/gcov ✔
633
        };
42 only COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
634
        if (colors.find(color) != colors.end()) {
126✔
635
                return true;
126✔
636
        }
637

638
        // does it start with "color"?
639
        if (color.size() > 5 && color.substr(0, 5) == "color") {
×
640
                if (color[5] == '0') {
×
641
                        // if the remainder of the string starts with zero, it can only be
642
                        // "color0"
643
                        return color == "color0" ? true : false;
×
644
                } else {
645
                        // we're now sure that the remainder doesn't start with zero, but
646
                        // is it a valid decimal number?
647
                        const std::string number = color.substr(5, color.size()-5);
×
648
                        size_t pos {};
×
649
                        int n = std::stoi(number, &pos);
×
650

651
                        // remainder should not contain any trailing characters
652
                        if (number.size() != pos) return false;
×
653

654
                        // remainder should be a number in (0; 255]. The interval is
655
                        // half-open because zero is already handled above.
656
                        if (n > 0 && n < 256) return true;
×
657
                }
×
658
        }
×
659
        return false;
×
660
}
93 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
661

662
bool utils::is_valid_attribute(const std::string& attrib) {
32 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
663
        static const std::unordered_set<std::string> attribs = {
113 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
664
                "standout", "underline", "reverse", "blink",
4 only COMPILER=clang++-3.7 GCOV=/usr/bin/gcov ✔
665
                "dim", "bold", "protect", "invis", "default"
5 only COMPILER=clang++-3.7 GCOV=/usr/bin/gcov ✔
666
        };
16 only COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
667
        if (attribs.find(attrib) != attribs.end()) {
48✔
668
                return true;
48✔
669
        } else {
670
                return false;
×
671
        }
672
}
41 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
673

674
std::vector<std::pair<unsigned int, unsigned int>> utils::partition_indexes(unsigned int start, unsigned int end, unsigned int parts) {
20 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
675
        std::vector<std::pair<unsigned int, unsigned int>> partitions;
30✔
676
        unsigned int count = end - start + 1;
30✔
677
        unsigned int size = count / parts;
30✔
678

679
        for (unsigned int i=0; i<parts-1; i++) {
2,090✔
680
                partitions.push_back(std::pair<unsigned int, unsigned int>(start, start + size - 1));
2,040✔
681
                start += size;
1,224✔
682
        }
816 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
683

684
        partitions.push_back(std::pair<unsigned int, unsigned int>(start, end));
50✔
685
        return partitions;
30✔
686
}
40 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
687

688
size_t utils::strwidth(const std::string& str) {
700 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
689
        std::wstring wstr = str2wstr(str);
1,225✔
690
        int width = wcswidth(wstr.c_str(), wstr.length());
1,400✔
691
        if (width < 1) // a non-printable character found?
1,050✔
692
                return wstr.length(); // return a sane width (which might be larger than necessary)
60✔
693
        return width; // exact width
990✔
694
}
700 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
695

696
size_t utils::strwidth_stfl(const std::string& str) {
688 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
697
        size_t reduce_count = 0;
1,032✔
698
        size_t len = str.length();
1,032✔
699
        if (len > 1) {
1,032✔
700
                for (size_t idx=0; idx<len-1; ++idx) {
8,700✔
701
                        if (str[idx] == '<' && str[idx+1] != '>') {
4,430✔
702
                                reduce_count += 3;
84✔
703
                                idx += 3;
84✔
704
                        }
56 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
705
                }
2,916 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
706
        }
564 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
707

708
        return strwidth(str) - reduce_count;
1,032✔
709
}
710

711
size_t utils::wcswidth_stfl(const std::wstring& str, size_t size) {
852 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
712
        size_t reduce_count = 0;
1,278✔
713
        size_t len = std::min(str.length(), size);
1,278✔
714
        if (len > 1) {
1,278✔
715
                for (size_t idx=0; idx<len-1; ++idx) {
49,820✔
716
                        if (str[idx] == L'<' && str[idx+1] != L'>') {
28,614✔
717
                                reduce_count += 3;
×
718
                                idx += 3;
×
719
                        }
×
720
                }
19,076 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
721
        }
852 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
722

723
        int width = wcswidth(str.c_str(), size);
1,278✔
724
        if (width < 0) {
1,278✔
725
                LOG(LOG_ERROR, "oh, oh, wcswidth just failed"); // : %ls", str.c_str());
×
726
                return str.length() - reduce_count;
×
727
        }
728

729
        return width - reduce_count;
1,278✔
730
}
852 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
731

732
std::string utils::join(const std::vector<std::string>& strings, const std::string& separator) {
24 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
733
        std::string result;
36✔
734

735
        for (auto str : strings) {
180✔
736
                result.append(str);
36✔
737
                result.append(separator);
36✔
738
        }
30 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 ✔
739

740
        if (result.length() > 0)
36✔
741
                result.erase(result.length()-separator.length(), result.length());
40✔
742

743
        return result;
36✔
744
}
48 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
745

746
bool utils::is_special_url(const std::string& url) {
96 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
747
        return url.substr(0,6) == "query:" || url.substr(0,7) == "filter:" || url.substr(0,5) == "exec:";
1,124✔
748
}
×
749

750
bool utils::is_http_url(const std::string& url) {
×
751
        return url.substr(0,7) == "http://" || url.substr(0,8) == "https://";
×
752
}
×
753

754
std::string utils::censor_url(const std::string& url) {
100 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
755
        std::string rv;
175✔
756
        if (url.length() > 0 && !utils::is_special_url(url)) {
342✔
757
                const char * myuri = url.c_str();
138✔
758
                xmlURIPtr uri = xmlParseURI(myuri);
230✔
759
                if (uri) {
138✔
760
                        if (uri->user) {
138✔
761
                                xmlFree(uri->user);
54✔
762
                                uri->user = (char *)xmlStrdup((const xmlChar *)"*:*");
90✔
763
                        }
36 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
764
                        xmlChar * uristr = xmlSaveUri(uri);
230✔
765

766
                        rv = (const char *)uristr;
138✔
767
                        xmlFree(uristr);
138✔
768
                        xmlFreeURI(uri);
138✔
769
                } else
92 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
770
                        return url;
×
771
        } else {
92 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
772
                rv = url;
12✔
773
        }
774
        return rv;
150✔
775
}
100 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
776

777
std::string utils::quote_for_stfl(std::string str) {
488 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
778
        unsigned int len = str.length();
1,098✔
779
        for (unsigned int i=0; i<len; ++i) {
10,970✔
780
                if (str[i] == '<') {
5,850✔
781
                        str.insert(i+1, ">");
6✔
782
                        ++len;
6✔
783
                }
4 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
784
        }
3,900 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
785
        return str;
732✔
786
}
787

788
void utils::trim(std::string& str) {
299 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
789
        while (str.length() > 0 && ::isspace(str[0])) {
1,381✔
790
                str.erase(0,1);
66✔
791
        }
22 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
792
        trim_end(str);
432✔
793
}
432✔
794

795
void utils::trim_end(std::string& str) {
356 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
796
        std::string::size_type pos = str.length()-1;
534✔
797
        while (str.length()>0 && (str[pos] == '\n' || str[pos] == '\r')) {
1,938✔
798
                str.erase(pos);
42✔
799
                pos--;
42✔
800
        }
14 only COMPILER=g++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog and COMPILER=clang++ GCOV=/usr/bin/gcov XML_CATALOG_FILES=/usr/local/etc/xml/catalog ✔
801
}
534✔
802

803
std::string utils::quote(const std::string& str) {
240 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
804
        std::string rv = replace_all(str, "\"", "\\\"");
1,080✔
805
        rv.insert(0, "\"");
360✔
806
        rv.append("\"");
360✔
807
        return rv;
360✔
808
}
480 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
809

810
unsigned int utils::get_random_value(unsigned int max) {
×
811
        static bool initialized = false;
812
        if (!initialized) {
×
813
                initialized = true;
×
814
                srand(~(time(NULL) ^ getpid() ^ getppid()));
×
815
        }
×
816
        return static_cast<unsigned int>(rand() % max);
×
817
}
818

819
std::string utils::quote_if_necessary(const std::string& str) {
×
820
        std::string result;
×
821
        if (str.find_first_of(" ", 0) == std::string::npos) {
×
822
                result = str;
×
823
        } else {
×
824
                result = utils::replace_all(str, "\"", "\\\"");
×
825
                result.insert(0, "\"");
×
826
                result.append("\"");
×
827
        }
828
        return result;
×
829
}
×
830

831
void utils::set_common_curl_options(CURL * handle, configcontainer * cfg) {
×
832
        std::string proxy;
×
833
        std::string proxyauth;
×
834
        std::string proxyauthmethod;
×
835
        std::string proxytype;
×
836
        std::string useragent;
×
837
        std::string cookie_cache;
×
838
        unsigned int dl_timeout = 0;
×
839

840
        if (cfg) {
×
841
                if (cfg->get_configvalue_as_bool("use-proxy")) {
×
842
                        proxy = cfg->get_configvalue("proxy");
×
843
                        proxyauth = cfg->get_configvalue("proxy-auth");
×
844
                        proxyauthmethod = cfg->get_configvalue("proxy-auth-method");
×
845
                        proxytype = cfg->get_configvalue("proxy-type");
×
846
                }
×
847
                useragent = utils::get_useragent(cfg);
×
848
                dl_timeout = cfg->get_configvalue_as_int("download-timeout");
×
849
                cookie_cache = cfg->get_configvalue("cookie-cache");
×
850
        }
×
851

852
        curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
×
853
        curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1);
×
854
        curl_easy_setopt(handle, CURLOPT_ENCODING, "gzip, deflate");
×
855
        curl_easy_setopt(handle, CURLOPT_TIMEOUT, dl_timeout);
×
856

857
        if (proxy != "")
×
858
                curl_easy_setopt(handle, CURLOPT_PROXY, proxy.c_str());
×
859
        if (proxyauth != "") {
×
860
                curl_easy_setopt(handle, CURLOPT_PROXYAUTH, get_auth_method(proxyauthmethod));
×
861
                curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, proxyauth.c_str());
×
862
        }
×
863
        if (proxytype != "") {
×
864
                LOG(LOG_DEBUG, "utils::set_common_curl_options: proxytype = %s", proxytype.c_str());
×
865
                curl_easy_setopt(handle, CURLOPT_PROXYTYPE, get_proxy_type(proxytype));
×
866
        }
×
867

868
        curl_easy_setopt(handle, CURLOPT_USERAGENT, useragent.c_str());
×
869

870
        curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
×
871
        curl_easy_setopt(handle, CURLOPT_MAXREDIRS, 10);
×
872
        curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);
×
873

874
        if (cookie_cache != "") {
×
875
                curl_easy_setopt(handle, CURLOPT_COOKIEFILE, cookie_cache.c_str());
×
876
                curl_easy_setopt(handle, CURLOPT_COOKIEJAR, cookie_cache.c_str());
×
877
        }
×
878
}
×
879

880
std::string utils::get_content(xmlNode * node) {
×
881
        std::string retval;
×
882
        if (node) {
×
883
                xmlChar * content = xmlNodeGetContent(node);
×
884
                if (content) {
×
885
                        retval = (const char *)content;
×
886
                        xmlFree(content);
×
887
                }
×
888
        }
×
889
        return retval;
×
890
}
×
891

892
std::string utils::get_prop(xmlNode * node, const char * prop, const char * ns) {
×
893
        std::string retval;
×
894
        if (node) {
×
895
                xmlChar * value;
×
896
                if (ns)
×
897
                        value = xmlGetProp(node, (xmlChar *)prop);
×
898
                else
899
                        value = xmlGetNsProp(node, (xmlChar *)prop, (xmlChar *)ns);
×
900
                if (value) {
×
901
                        retval = (const char*)value;
×
902
                        xmlFree(value);
×
903
                }
×
904
        }
×
905
        return retval;
×
906
}
×
907

908
unsigned long utils::get_auth_method(const std::string& type) {
×
909
        if (type == "any")
×
910
                return CURLAUTH_ANY;
×
911
        if (type == "basic")
×
912
                return CURLAUTH_BASIC;
×
913
        if (type == "digest")
×
914
                return CURLAUTH_DIGEST;
×
915
#ifdef CURLAUTH_DIGEST_IE
916
        if (type == "digest_ie")
×
917
                return CURLAUTH_DIGEST_IE;
×
918
#else
919
# warning "proxy-auth-method digest_ie not added due to libcurl older than 7.19.3"
920
#endif
921
        if (type == "gssnegotiate")
×
922
                return CURLAUTH_GSSNEGOTIATE;
×
923
        if (type == "ntlm")
×
924
                return CURLAUTH_NTLM;
×
925
        if (type == "anysafe")
×
926
                return CURLAUTH_ANYSAFE;
×
927
        if (type != "") {
×
928
                LOG(LOG_USERERROR, "you configured an invalid proxy authentication method: %s", type.c_str());
×
929
        }
×
930
        return CURLAUTH_ANY;
×
931
}
×
932

933
curl_proxytype utils::get_proxy_type(const std::string& type) {
×
934
        if (type == "http")
×
935
                return CURLPROXY_HTTP;
×
936
        if (type == "socks4")
×
937
                return CURLPROXY_SOCKS4;
×
938
        if (type == "socks5")
×
939
                return CURLPROXY_SOCKS5;
×
940
#ifdef CURLPROXY_SOCKS4A
941
        if (type == "socks4a")
942
                return CURLPROXY_SOCKS4A;
943
#endif
944

945
        if (type != "") {
×
946
                LOG(LOG_USERERROR, "you configured an invalid proxy type: %s", type.c_str());
×
947
        }
×
948
        return CURLPROXY_HTTP;
×
949
}
×
950

951
std::string utils::escape_url(const std::string& url) {
×
952
        return replace_all(replace_all(url,"?","%3F"), "&", "%26");
×
953
}
×
954

955
std::string utils::unescape_url(const std::string& url) {
×
956
        return replace_all(replace_all(url,"%3F","?"), "%26", "&");
×
957
}
×
958

959
std::wstring utils::clean_nonprintable_characters(std::wstring text) {
100 all except COMPILER=clang++-3.7 GCOV=/usr/bin/gcov and COMPILER=clang++-3.6 GCOV=/usr/bin/gcov ✔
960
        for (size_t idx=0; idx<text.size(); ++idx) {
4,185✔
961
                if (!iswprint(text[idx]))
2,316✔
962
                        text[idx] = L'\uFFFD';
×
963
        }
1,544 all except COMPILER=g++-5 GCOV=/usr/bin/gcov-5 and COMPILER=g++-4.9 GCOV=/usr/bin/gcov-4.9 ✔
964
        return text;
150✔
965
}
966

967
unsigned int utils::gentabs(const std::string& str) {
×
968
        int tabcount = 4 - (utils::strwidth(str) / 8);
×
969
        if (tabcount <= 0) {
×
970
                tabcount = 1;
×
971
        }
×
972
        return tabcount;
×
973
}
974

975
/* Like mkdir(), but creates ancestors (parent directories) if they don't
976
 * exist. */
977
int utils::mkdir_parents(const char* p, mode_t mode) {
×
978
        int result;
×
979

980
        /* Have to copy the path because we're going to modify it */
981
        char* pathname = (char*)malloc(strlen(p) + 1);
×
982
        strcpy(pathname, p);
×
983
        /* This pointer will run through the whole string looking for '/'.
984
         * We move it by one if path starts with slash because if we don't, the
985
         * first call to access() will fail (because of empty path) */
986
        char* curr = pathname + (*pathname == '/' ? 1 : 0);
×
987

988
        while (*curr) {
×
989
                if (*curr == '/') {
×
990
                        *curr = '\0';
×
991
                        result = access(pathname, F_OK);
×
992
                        if (result == -1) {
×
993
                                result = mkdir(pathname, mode);
×
994
                                if (result != 0)
×
995
                                        break;
×
996
                        }
×
997
                        *curr = '/';
×
998
                }
×
999
                curr++;
×
1000
        }
×
1001

1002
        if (result == 0) mkdir(p, mode);
×
1003

1004
        free(pathname);
×
1005
        return result;
×
1006
}
1007

1008
/*
1009
 * See http://curl.haxx.se/libcurl/c/libcurl-tutorial.html#Multi-threading for a reason why we do this.
1010
 */
1011

1012
#if HAVE_OPENSSL
1013
static std::mutex * openssl_mutexes = NULL;
1014
static int openssl_mutexes_size = 0;
1015

1016
static void openssl_mth_locking_function(int mode, int n, const char * file, int line) {
×
1017
        if (n < 0 || n >= openssl_mutexes_size) {
×
1018
                LOG(LOG_ERROR,"openssl_mth_locking_function: index is out of bounds (called by %s:%d)", file, line);
×
1019
                return;
×
1020
        }
1021
        if (mode & CRYPTO_LOCK) {
×
1022
                LOG(LOG_DEBUG, "OpenSSL lock %d: %s:%d", n, file, line);
×
1023
                openssl_mutexes[n].lock();
×
1024
        } else {
×
1025
                LOG(LOG_DEBUG, "OpenSSL unlock %d: %s:%d", n, file, line);
×
1026
                openssl_mutexes[n].unlock();
×
1027
        }
1028
}
×
1029

1030
static unsigned long openssl_mth_id_function(void) {
×
1031
        return (unsigned long)pthread_self();
×
1032
}
1033
#endif
1034

1035
void utils::initialize_ssl_implementation(void) {
×
1036
#if HAVE_OPENSSL
1037
        openssl_mutexes_size = CRYPTO_num_locks();
×
1038
        openssl_mutexes = new std::mutex[openssl_mutexes_size];
×
1039
        CRYPTO_set_id_callback(openssl_mth_id_function);
×
1040
        CRYPTO_set_locking_callback(openssl_mth_locking_function);
×
1041
#endif
1042

1043
#if HAVE_GCRYPT
1044
        gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
1045
        gnutls_global_init();
1046
#endif
1047
}
×
1048

1049
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc