~ubuntu-branches/ubuntu/wily/mediatomb/wily

« back to all changes in this revision

Viewing changes to .pc/0004_const_char_conversion.patch/src/tools.cc

  • Committer: Package Import Robot
  • Author(s): Logan Rosen
  • Date: 2013-12-28 23:22:35 UTC
  • mfrom: (4.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20131228232235-uhxpo82dnqa3cw95
Tags: 0.12.1-5ubuntu1
Merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*MT*
 
2
    
 
3
    MediaTomb - http://www.mediatomb.cc/
 
4
    
 
5
    tools.cc - this file is part of MediaTomb.
 
6
    
 
7
    Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
 
8
                       Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
 
9
    
 
10
    Copyright (C) 2006-2010 Gena Batyan <bgeradz@mediatomb.cc>,
 
11
                            Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
 
12
                            Leonhard Wimmer <leo@mediatomb.cc>
 
13
    
 
14
    MediaTomb is free software; you can redistribute it and/or modify
 
15
    it under the terms of the GNU General Public License version 2
 
16
    as published by the Free Software Foundation.
 
17
    
 
18
    MediaTomb is distributed in the hope that it will be useful,
 
19
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
    GNU General Public License for more details.
 
22
    
 
23
    You should have received a copy of the GNU General Public License
 
24
    version 2 along with MediaTomb; if not, write to the Free Software
 
25
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
26
    
 
27
    $Id: tools.cc 2081 2010-03-23 20:18:00Z lww $
 
28
*/
 
29
 
 
30
/// \file tools.cc
 
31
 
 
32
#ifdef HAVE_CONFIG_H
 
33
    #include "autoconfig.h"
 
34
#endif
 
35
 
 
36
#include "tools.h"
 
37
#include <sys/stat.h>
 
38
#include <errno.h>
 
39
#include <unistd.h>
 
40
#include <sys/ioctl.h>
 
41
#include <sys/socket.h>
 
42
#include <netinet/in.h>
 
43
#include <arpa/inet.h>
 
44
#include <limits.h>
 
45
#include <netdb.h>
 
46
#include <string.h>
 
47
#include "config_manager.h"
 
48
 
 
49
#ifndef SOLARIS
 
50
    #include <net/if.h>
 
51
#else
 
52
    #include <fcntl.h>
 
53
    #include <net/if.h>
 
54
    #include <sys/sockio.h>
 
55
#endif
 
56
 
 
57
#include "md5/md5.h"
 
58
#include "file_io_handler.h"
 
59
#include "metadata_handler.h"
 
60
 
 
61
#define WHITE_SPACE " \t\r\n"
 
62
 
 
63
using namespace zmm;
 
64
 
 
65
static const char *HEX_CHARS = "0123456789abcdef";
 
66
 
 
67
Ref<Array<StringBase> > split_string(String str, char sep, bool empty)
 
68
{
 
69
    Ref<Array<StringBase> > ret(new Array<StringBase>());
 
70
    char *data = str.c_str();
 
71
    char *end = data + str.length();
 
72
    while (data < end)
 
73
    {
 
74
        char *pos = strchr(data, sep);
 
75
        if (pos == NULL)
 
76
        {
 
77
            String part = data;
 
78
            ret->append(part);
 
79
            data = end;
 
80
        }
 
81
        else if (pos == data)
 
82
        {
 
83
            data++;
 
84
            if ((data < end) && empty)
 
85
                ret->append(_(""));
 
86
        }
 
87
        else
 
88
        {
 
89
            String part(data, pos - data);
 
90
            ret->append(part);
 
91
            data = pos + 1;
 
92
        }
 
93
    }
 
94
    return ret;
 
95
}
 
96
 
 
97
Ref<Array<StringBase> > split_path(String str)
 
98
{
 
99
    if (! string_ok(str))
 
100
        throw _Exception(_("invalid path given to split_path"));
 
101
    Ref<Array<StringBase> > ret(new Array<StringBase>());
 
102
    int pos = str.rindex(DIR_SEPARATOR);
 
103
    const char *data = str.c_str();
 
104
    
 
105
    if (pos < 0)
 
106
        throw _Exception(_("relative path given to split_path: ") + str);
 
107
    
 
108
    if (pos == 0)
 
109
    {
 
110
        /* there is only one separator at the beginning "/..." or "/" */
 
111
        ret->append(_(_DIR_SEPARATOR));
 
112
        String filename = data + 1;
 
113
        ret->append(filename);
 
114
    }
 
115
    else
 
116
    {
 
117
        String path(data, pos);
 
118
        ret->append(path);
 
119
        String filename = data + pos + 1;
 
120
        ret->append(filename);
 
121
    }
 
122
    return ret;
 
123
}
 
124
 
 
125
String trim_string(String str)
 
126
{
 
127
    if (str == nil)
 
128
        return nil;
 
129
    int i;
 
130
    int start = 0;
 
131
    int end = 0;
 
132
    int len = str.length();
 
133
 
 
134
    char *buf = str.c_str();
 
135
 
 
136
    for (i = 0; i < len; i++)
 
137
    {
 
138
        if (! strchr(WHITE_SPACE, buf[i]))
 
139
        {
 
140
            start = i;
 
141
            break;
 
142
        }
 
143
    }
 
144
    if (i >= len)
 
145
        return _("");
 
146
    for (i = len - 1; i >= start; i--)
 
147
    {
 
148
        if (! strchr(WHITE_SPACE, buf[i]))
 
149
        {
 
150
            end = i + 1;
 
151
            break;
 
152
        }
 
153
    }
 
154
    return str.substring(start, end - start);
 
155
}
 
156
 
 
157
bool check_path(String path, bool needDir)
 
158
{
 
159
    int ret = 0;
 
160
    struct stat statbuf;
 
161
 
 
162
    ret = stat(path.c_str(), &statbuf);
 
163
    if (ret != 0) return false;
 
164
 
 
165
    if ((needDir && (!S_ISDIR(statbuf.st_mode))) ||
 
166
       (!needDir && (S_ISDIR(statbuf.st_mode)))) return false;
 
167
 
 
168
    return true;
 
169
}
 
170
 
 
171
time_t check_path_ex(String path, bool needDir, bool existenceUnneeded, 
 
172
        off_t *filesize)
 
173
{
 
174
    int ret = 0;
 
175
    struct stat statbuf;
 
176
 
 
177
    if (filesize != NULL)
 
178
        *filesize = 0;
 
179
 
 
180
    ret = stat(path.c_str(), &statbuf);
 
181
    if (ret != 0)
 
182
    {
 
183
        if (existenceUnneeded && (errno == ENOENT))
 
184
            return 0;
 
185
        
 
186
        throw _Exception(path + " : " + errno + (int)existenceUnneeded+ " x " + mt_strerror(errno));
 
187
    }
 
188
 
 
189
    if (needDir && (!S_ISDIR(statbuf.st_mode)))
 
190
        throw _Exception(_("Not a directory: ") + path);
 
191
    
 
192
    if (!needDir && (S_ISDIR(statbuf.st_mode)))
 
193
        throw _Exception(_("Not a file: ") + path);
 
194
 
 
195
    if ((filesize != NULL) && S_ISREG(statbuf.st_mode))
 
196
        *filesize = statbuf.st_size;
 
197
 
 
198
    return statbuf.st_mtime;
 
199
}
 
200
 
 
201
bool is_executable(String path, int *err)
 
202
{
 
203
    int ret = access(path.c_str(), R_OK | X_OK);
 
204
    if (err != NULL)
 
205
        *err = errno;
 
206
 
 
207
    if (ret == 0)
 
208
        return true;
 
209
    else 
 
210
        return false;
 
211
}
 
212
 
 
213
String find_in_path(String exec)
 
214
{
 
215
    String PATH = getenv("PATH");
 
216
    if (!string_ok(PATH))
 
217
        return nil;
 
218
 
 
219
    Ref<StringTokenizer> st(new StringTokenizer(PATH));
 
220
    String path = nil;
 
221
    String next;
 
222
    do
 
223
    {
 
224
        if (path == nil)
 
225
            path = st->nextToken(_(":"));
 
226
        next = st->nextToken(_(":"));
 
227
 
 
228
        if (path == nil)
 
229
            break;
 
230
 
 
231
        if ((next != nil) && !next.startsWith(_("/")))
 
232
        {
 
233
            path = path + _(":") + next;
 
234
            next = nil;
 
235
        }
 
236
 
 
237
        String check = path + _("/") + exec;
 
238
        if (check_path(check))
 
239
            return check;
 
240
 
 
241
        if (next != nil)
 
242
            path = next;
 
243
        else
 
244
            path = nil;
 
245
 
 
246
 
 
247
    } while (path != nil);
 
248
 
 
249
    return nil;
 
250
}
 
251
 
 
252
bool string_ok(String str)
 
253
{
 
254
    if ((str == nil) || (str == ""))
 
255
        return false;
 
256
    return true;
 
257
}
 
258
 
 
259
bool string_ok(Ref<StringBuffer> str)
 
260
{
 
261
    
 
262
    if ((str == nil) || (str->length()<=0))
 
263
        return false;
 
264
    else
 
265
        return true;
 
266
}
 
267
 
 
268
void string_ok_ex(String str)
 
269
{
 
270
    if ((str == nil) || (str == ""))
 
271
        throw _Exception(_("Empty string"));
 
272
}
 
273
 
 
274
String http_redirect_to(String ip, String port, String page)
 
275
{
 
276
    return _("<html><head><meta http-equiv=\"Refresh\" content=\"0;URL=http://") + ip + ":" + port + "/" + page + "\"></head><body bgcolor=\"#dddddd\"></body></html>";
 
277
}
 
278
 
 
279
String hex_encode(void *data, int len)
 
280
{
 
281
    unsigned char *chars;
 
282
    int i;
 
283
    unsigned char hi, lo;
 
284
 
 
285
    Ref<StringBuffer> buf(new StringBuffer(len * 2));
 
286
    
 
287
    chars = (unsigned char *)data;
 
288
    for (i = 0; i < len; i++)
 
289
    {
 
290
        unsigned char c = chars[i];
 
291
        hi = c >> 4;
 
292
        lo = c & 0xF;
 
293
        *buf << HEX_CHARS[hi] << HEX_CHARS[lo];
 
294
    }
 
295
    return buf->toString();
 
296
    
 
297
}
 
298
 
 
299
String hex_decode_string(String encoded)
 
300
{
 
301
    char *ptr = encoded.c_str();
 
302
    int len = encoded.length();
 
303
    
 
304
    Ref<StringBuffer> buf(new StringBuffer(len / 2));
 
305
    for (int i = 0; i < len; i += 2)
 
306
    {
 
307
        const char *chi = strchr(HEX_CHARS, ptr[i]);
 
308
        const char *clo = strchr(HEX_CHARS, ptr[i + 1]);
 
309
        int hi, lo;
 
310
        
 
311
        if (chi)
 
312
            hi = chi - HEX_CHARS;
 
313
        else
 
314
            hi = 0;
 
315
 
 
316
        if (clo)
 
317
            lo = clo - HEX_CHARS;
 
318
        else
 
319
            lo = 0;
 
320
        char ch = (char)(hi << 4 | lo);
 
321
        *buf << ch;
 
322
    }
 
323
    return buf->toString();
 
324
}
 
325
 
 
326
struct randomizer
 
327
{
 
328
    struct timeval tv;
 
329
    int salt;
 
330
};
 
331
String hex_md5(void *data, int length)
 
332
{
 
333
    char md5buf[16];
 
334
 
 
335
    md5_state_t ctx;
 
336
    md5_init(&ctx);
 
337
    md5_append(&ctx, (unsigned char *)data, length);
 
338
    md5_finish(&ctx, (unsigned char *)md5buf);
 
339
 
 
340
    return hex_encode(md5buf, 16);
 
341
}
 
342
String hex_string_md5(String str)
 
343
{
 
344
    return hex_md5(str.c_str(), str.length());
 
345
}
 
346
String generate_random_id()
 
347
{
 
348
    struct randomizer st;
 
349
    gettimeofday(&st.tv, NULL);
 
350
    st.salt = rand();
 
351
    return hex_md5(&st, sizeof(st));
 
352
}
 
353
 
 
354
 
 
355
static const char *hex = "0123456789ABCDEF";
 
356
 
 
357
String url_escape(String str)
 
358
{
 
359
    char *data = str.c_str();
 
360
    int len = str.length();
 
361
    Ref<StringBuffer> buf(new StringBuffer(len));
 
362
    for (int i = 0; i < len; i++)
 
363
    {
 
364
        unsigned char c = (unsigned char)data[i];
 
365
        if ((c >= '0' && c <= '9') ||
 
366
            (c >= 'A' && c <= 'Z') ||
 
367
            (c >= 'a' && c <= 'z') ||
 
368
            c == '_' ||
 
369
            c == '-')
 
370
        {
 
371
            *buf << (char)c;
 
372
        }
 
373
        else
 
374
        {
 
375
            int hi = c >> 4;
 
376
            int lo = c & 15;
 
377
            *buf << '%' << hex[hi] << hex[lo];
 
378
        }
 
379
    }
 
380
    return buf->toString();
 
381
}
 
382
 
 
383
String url_unescape(String str)
 
384
{
 
385
    char *data = str.c_str();
 
386
    int len = str.length();
 
387
    Ref<StringBuffer> buf(new StringBuffer(len));
 
388
 
 
389
    int i = 0;
 
390
    while (i < len)
 
391
    {
 
392
        char c = data[i++];
 
393
        if (c == '%')
 
394
        {
 
395
            if (i + 2 > len)
 
396
                break; // avoid buffer overrun
 
397
            char chi = data[i++];
 
398
            char clo = data[i++];
 
399
            int hi, lo;
 
400
 
 
401
            const char *pos;
 
402
 
 
403
            pos = strchr(hex, chi);
 
404
            if (!pos)
 
405
                hi = 0;
 
406
            else
 
407
                hi = pos - hex;
 
408
 
 
409
            pos = strchr(hex, clo);
 
410
            if (!pos)
 
411
                lo = 0;
 
412
            else
 
413
                lo = pos - hex;
 
414
 
 
415
            int ascii = (hi << 4) | lo;
 
416
            *buf << (char)ascii;
 
417
        }
 
418
        else if (c == '+')
 
419
        {
 
420
            *buf << ' ';
 
421
        }
 
422
        else
 
423
        {
 
424
            *buf << c;
 
425
        }
 
426
    }
 
427
    return buf->toString();
 
428
}
 
429
 
 
430
String mime_types_to_CSV(Ref<Array<StringBase> > mimeTypes)
 
431
{
 
432
    Ref<StringBuffer> buf(new StringBuffer());
 
433
    for (int i = 0; i < mimeTypes->size(); i++)
 
434
    {
 
435
        if (i > 0)
 
436
            *buf << ",";
 
437
        String mimeType = mimeTypes->get(i);
 
438
        *buf << "http-get:*:" << mimeType << ":*";
 
439
    }
 
440
 
 
441
    return buf->toString();
 
442
}
 
443
 
 
444
String mt_strerror(int mt_errno)
 
445
{
 
446
#ifdef DONT_USE_YET_HAVE_STRERROR_R
 
447
    char *buffer = (char *)MALLOC(512);
 
448
    char *err_str;
 
449
    #ifdef STRERROR_R_CHAR_P
 
450
        err_str = strerror_r(errno, buffer, 512);
 
451
        if (err_str == NULL)
 
452
            err_str = buffer;
 
453
    #else
 
454
        int ret = strerror_r(errno, buffer, 512);
 
455
        if (ret < 0)
 
456
            return _("cannot get error string: error while calling XSI-compliant strerror_r");
 
457
        err_str = buffer;
 
458
    #endif
 
459
    String errStr(err_str);
 
460
    FREE(buffer);
 
461
    return errStr;
 
462
#else
 
463
    return strerror(errno);
 
464
#endif
 
465
}
 
466
 
 
467
String read_text_file(String path)
 
468
{
 
469
    FILE *f = fopen(path.c_str(), "r");
 
470
    if (!f)
 
471
    {
 
472
        throw _Exception(_("read_text_file: could not open ") +
 
473
                        path + " : " + mt_strerror(errno));
 
474
    }
 
475
    Ref<StringBuffer> buf(new StringBuffer()); 
 
476
    char *buffer = (char *)MALLOC(1024);
 
477
    size_t bytesRead;    
 
478
    while((bytesRead = fread(buffer, 1, 1024, f)) > 0)
 
479
    {
 
480
        buf->concat(buffer, bytesRead);
 
481
    }
 
482
    fclose(f);
 
483
    FREE(buffer);
 
484
    return buf->toString();
 
485
}
 
486
void write_text_file(String path, String contents)
 
487
{
 
488
    int bytesWritten;
 
489
    FILE *f = fopen(path.c_str(), "w");
 
490
    if (!f)
 
491
    {
 
492
        throw _Exception(_("write_text_file: could not open ") +
 
493
                        path + " : " + mt_strerror(errno));
 
494
    }
 
495
    
 
496
    bytesWritten = fwrite(contents.c_str(), 1, contents.length(), f);
 
497
    if (bytesWritten < contents.length())
 
498
    {
 
499
        fclose(f);
 
500
        if (bytesWritten >= 0)
 
501
            throw _Exception(_("write_text_file: incomplete write to ") +
 
502
                            path + " : ");
 
503
        else
 
504
            throw _Exception(_("write_text_file: error writing to ") +
 
505
                            path + " : " + mt_strerror(errno));
 
506
    }
 
507
    fclose(f);
 
508
}
 
509
 
 
510
void copy_file(String from, String to)
 
511
{
 
512
    FILE *f = fopen(from.c_str(), "r");
 
513
    if (!f)
 
514
    {
 
515
        throw _Exception(_("copy_file: could not open ") +
 
516
                        from + " for read: " + mt_strerror(errno));
 
517
    }
 
518
    FILE *t = fopen(to.c_str(), "w");
 
519
    if (!t)
 
520
    {
 
521
        fclose(f);
 
522
        throw _Exception(_("copy_file: could not open ") +
 
523
                        to + " for write: " + mt_strerror(errno));
 
524
    }
 
525
    char *buffer = (char *)MALLOC(1024);
 
526
    size_t bytesRead = 0;
 
527
    size_t bytesWritten = 0;
 
528
    while(bytesRead == bytesWritten && ! feof(f) && ! ferror(f) && ! ferror(t)
 
529
        && (bytesRead = fread(buffer, 1, 1024, f)) > 0)
 
530
    {
 
531
        bytesWritten = fwrite(buffer, 1, bytesRead, t);
 
532
    }
 
533
    FREE(buffer);
 
534
    if (ferror(f) || ferror(t))
 
535
    {
 
536
        int my_errno = errno;
 
537
        fclose(f);
 
538
        fclose(t);
 
539
        throw _Exception(_("copy_file: error while copying ") + from + " to " +
 
540
                        to + ": " + mt_strerror(my_errno));
 
541
    }
 
542
    
 
543
    fclose(f);
 
544
    fclose(t);
 
545
}
 
546
 
 
547
/* sorting */
 
548
int StringBaseComparator(void *arg1, void *arg2)
 
549
{
 
550
    return strcmp(((StringBase *)arg1)->data, ((StringBase *)arg2)->data); 
 
551
}
 
552
 
 
553
static void quicksort_impl(COMPARABLE *a, int lo0, int hi0, COMPARATOR comparator)
 
554
{
 
555
    int lo = lo0;
 
556
    int hi = hi0;
 
557
 
 
558
    if (lo >= hi)
 
559
        return;
 
560
    if( lo == hi - 1 )
 
561
    {
 
562
        // sort a two element list by swapping if necessary 
 
563
        // if (a[lo] > a[hi])
 
564
        if (comparator(a[lo], a[hi]) > 0)
 
565
        {
 
566
            COMPARABLE T = a[lo];
 
567
            a[lo] = a[hi];
 
568
            a[hi] = T;
 
569
        }
 
570
        return;
 
571
    }
 
572
 
 
573
    // Pick a pivot and move it out of the way
 
574
    COMPARABLE pivot = a[(lo + hi) / 2];
 
575
    a[(lo + hi) / 2] = a[hi];
 
576
    a[hi] = pivot;
 
577
 
 
578
    while( lo < hi )
 
579
    {
 
580
        /* Search forward from a[lo] until an element is found that
 
581
           is greater than the pivot or lo >= hi */ 
 
582
        // while (a[lo] <= pivot && lo < hi)
 
583
        while (comparator(a[lo], pivot) <= 0 && lo < hi)
 
584
        {
 
585
            lo++;
 
586
        }
 
587
 
 
588
        /* Search backward from a[hi] until element is found that
 
589
           is less than the pivot, or lo >= hi */
 
590
        // while (pivot <= a[hi] && lo < hi )
 
591
        while (comparator(pivot, a[hi]) <= 0 && lo < hi)
 
592
        {
 
593
            hi--;
 
594
        }
 
595
 
 
596
        /* Swap elements a[lo] and a[hi] */
 
597
        if( lo < hi )
 
598
        {
 
599
            COMPARABLE T = a[lo];
 
600
            a[lo] = a[hi];
 
601
            a[hi] = T;
 
602
        }
 
603
    }
 
604
 
 
605
    /* Put the median in the "center" of the list */
 
606
    a[hi0] = a[hi];
 
607
    a[hi] = pivot;
 
608
 
 
609
    /*
 
610
     *  Recursive calls, elements a[lo0] to a[lo-1] are less than or
 
611
     *  equal to pivot, elements a[hi+1] to a[hi0] are greater than
 
612
     *  pivot.
 
613
     */
 
614
    quicksort_impl(a, lo0, lo-1, comparator);
 
615
    quicksort_impl(a, hi+1, hi0, comparator);
 
616
}
 
617
 
 
618
void quicksort(COMPARABLE *arr, int size, COMPARATOR comparator)
 
619
{
 
620
    quicksort_impl(arr, 0, size - 1, comparator);
 
621
}
 
622
 
 
623
String renderProtocolInfo(String mimetype, String protocol, String extend)
 
624
{
 
625
    if (string_ok(mimetype) && string_ok(protocol))
 
626
    {
 
627
        if (string_ok(extend))
 
628
            return protocol + ":*:" + mimetype + ":" + extend;
 
629
        else
 
630
            return protocol + ":*:" + mimetype + ":*";
 
631
    }
 
632
    else
 
633
        return _("http-get:*:*:*");
 
634
}
 
635
 
 
636
String getMTFromProtocolInfo(String protocol)
 
637
{
 
638
    Ref<Array<StringBase> > parts = split_string(protocol, ':');
 
639
    if (parts->size() > 2)
 
640
        return parts->get(2);
 
641
    else
 
642
        return nil;
 
643
}
 
644
 
 
645
String getProtocol(String protocolInfo)
 
646
{
 
647
    String protocol;
 
648
    int pos = protocolInfo.index(':');
 
649
    if (pos <= 0)
 
650
        protocol = _("http-get");
 
651
    else
 
652
        protocol = protocolInfo.substring(0, pos);
 
653
 
 
654
    return protocol;
 
655
}
 
656
 
 
657
String secondsToHMS(int seconds)
 
658
{
 
659
    int h, m, s;
 
660
    
 
661
    s = seconds % 60;
 
662
    seconds /= 60;
 
663
 
 
664
    m = seconds % 60;
 
665
    h = seconds / 60;
 
666
 
 
667
    // XXX:XX:XX
 
668
    char *str = (char *)malloc(10);
 
669
    sprintf(str, "%02d:%02d:%02d", h, m, s);
 
670
    return String::take(str);
 
671
}
 
672
 
 
673
int HMSToSeconds(String time)
 
674
{
 
675
    if (!string_ok(time))
 
676
    {
 
677
        log_warning("Could not convert time representation to seconds!\n");
 
678
        return 0;
 
679
    }
 
680
 
 
681
    int hours = 0;
 
682
    int minutes = 0;
 
683
    int seconds = 0;
 
684
    sscanf(time.c_str(), "%d:%d:%d", &hours, &minutes, &seconds);
 
685
 
 
686
    return (hours * 3600) + (minutes * 60) + seconds;
 
687
}
 
688
 
 
689
#ifdef HAVE_MAGIC
 
690
String get_mime_type(magic_set *ms, Ref<RExp> reMimetype, String file)
 
691
{
 
692
    if (ms == NULL)
 
693
        return nil;
 
694
 
 
695
    char *mt = (char *)magic_file(ms, file.c_str());
 
696
    if (mt == NULL)
 
697
    {
 
698
        log_error("magic_file: %s\n", magic_error(ms));
 
699
        return nil;
 
700
    }
 
701
 
 
702
    String mime_type = mt;
 
703
 
 
704
    Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
 
705
    if (matcher->next())
 
706
        return matcher->group(1);
 
707
 
 
708
    log_warning("filemagic returned invalid mimetype for %s\n%s\n",
 
709
                file.c_str(), mt);
 
710
    return nil;
 
711
}
 
712
 
 
713
String get_mime_type_from_buffer(magic_set *ms, Ref<RExp> reMimetype, 
 
714
                                 void *buffer, size_t length)
 
715
{
 
716
    if (ms == NULL)
 
717
        return nil;
 
718
 
 
719
    char *mt = (char *)magic_buffer(ms, buffer, length);
 
720
    if (mt == NULL)
 
721
    {
 
722
        log_error("magic_file: %s\n", magic_error(ms));
 
723
        return nil;
 
724
    }
 
725
 
 
726
    String mime_type = mt;
 
727
 
 
728
    Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
 
729
    if (matcher->next())
 
730
        return matcher->group(1);
 
731
 
 
732
    log_warning("filemagic returned invalid mimetype for the given buffer%s\n",
 
733
                mt);
 
734
    return nil;
 
735
}
 
736
#endif 
 
737
 
 
738
void set_jpeg_resolution_resource(Ref<CdsItem> item, int res_num)
 
739
{
 
740
    try
 
741
    {
 
742
        Ref<IOHandler> fio_h(new FileIOHandler(item->getLocation()));
 
743
        fio_h->open(UPNP_READ);
 
744
        String resolution = get_jpeg_resolution(fio_h);
 
745
 
 
746
        if (res_num >= item->getResourceCount())
 
747
            throw _Exception(_("Invalid resource index"));
 
748
            
 
749
        item->getResource(res_num)->addAttribute(MetadataHandler::getResAttrName(R_RESOLUTION), resolution);
 
750
    }
 
751
    catch (Exception e)
 
752
    {
 
753
        e.printStackTrace();
 
754
    }
 
755
}
 
756
 
 
757
bool check_resolution(String resolution, int *x, int *y)
 
758
{
 
759
    if (x != NULL)
 
760
        *x = 0;
 
761
 
 
762
    if (y != NULL)
 
763
        *y = 0;
 
764
 
 
765
    Ref<Array<StringBase> > parts = split_string(resolution, 'x');
 
766
    if (parts->size() != 2)
 
767
        return false;
 
768
 
 
769
    if (string_ok(parts->get(0)) && 
 
770
        string_ok(parts->get(1)))
 
771
        {
 
772
            int _x = _(parts->get(0)->data).toInt();
 
773
            int _y = _(parts->get(1)->data).toInt();
 
774
 
 
775
            if ((_x > 0) && (_y > 0))
 
776
            {
 
777
                if (x != NULL)
 
778
                    *x = _x;
 
779
 
 
780
                if (y != NULL)
 
781
                    *y = _y;
 
782
 
 
783
                return true;
 
784
            }
 
785
        }
 
786
        
 
787
    return false;
 
788
}
 
789
 
 
790
 
 
791
String escape(String string, char escape_char, char to_escape)
 
792
{
 
793
    Ref<StringBase> stringBase(new StringBase(string.length() * 2));
 
794
    char *str = stringBase->data;
 
795
    int len = string.length();
 
796
    
 
797
    bool possible_more_esc = true;
 
798
    bool possible_more_char = true;
 
799
    
 
800
    int last = 0;
 
801
    do
 
802
    {
 
803
        int next_esc = -1;
 
804
        if (possible_more_esc)
 
805
        {
 
806
            next_esc = string.index(last, escape_char);
 
807
            if (next_esc < 0)
 
808
                possible_more_esc = false;
 
809
        }
 
810
        
 
811
        int next = -1;
 
812
        if (possible_more_char)
 
813
        {
 
814
            next = string.index(last, to_escape);
 
815
            if (next < 0)
 
816
                possible_more_char = false;
 
817
        }
 
818
        
 
819
        if (next < 0 || (next_esc >= 0 && next_esc < next))
 
820
        {
 
821
            next = next_esc;
 
822
        }
 
823
        
 
824
        if (next < 0)
 
825
            next = len;
 
826
        int cpLen = next - last;
 
827
        if (cpLen > 0)
 
828
        {
 
829
            strncpy(str, string.charPtrAt(last), cpLen);
 
830
            str += cpLen;
 
831
        }
 
832
        if (next < len)
 
833
        {
 
834
            *(str++) = '\\';
 
835
            *(str++) = string.charAt(next);
 
836
        }
 
837
        last = next;
 
838
        last++;
 
839
    }
 
840
    while (last < len);
 
841
    *str = '\0';
 
842
    
 
843
    stringBase->len = strlen(stringBase->data);
 
844
    return stringBase->data;
 
845
}
 
846
 
 
847
String unescape(String string, char escape)
 
848
{
 
849
    Ref<StringBase> stringBase(new StringBase(string.length()));
 
850
    char *str = stringBase->data;
 
851
    int len = string.length();
 
852
    
 
853
    int last = -1;
 
854
    do
 
855
    {
 
856
        int next = string.index(last + 1, escape);
 
857
        if (next < 0)
 
858
            next = len;
 
859
        if (last < 0)
 
860
            last = 0;
 
861
        int cpLen = next - last;
 
862
        if (cpLen > 0)
 
863
            strncpy(str, string.charPtrAt(last), cpLen);
 
864
        str += cpLen;
 
865
        last = next;
 
866
        last++;
 
867
    }
 
868
    while (last < len);
 
869
    *str = '\0';
 
870
    
 
871
    stringBase->len = strlen(stringBase->data);
 
872
    return String(stringBase);
 
873
}
 
874
 
 
875
/*
 
876
String xml_unescape(String string)
 
877
{
 
878
    Ref<StringBuffer> buf(new StringBuffer(string.length()));
 
879
    signed char *ptr = (signed char *)string.c_str();
 
880
    while (*ptr)
 
881
    {
 
882
        if (*ptr == '&')
 
883
        {
 
884
            if ((*(ptr + 1) == 'l') && (*(ptr + 2) == 't') && 
 
885
                (*(ptr + 3) == ';'))
 
886
            {
 
887
                *buf << '<';
 
888
                ptr = ptr + 3;
 
889
            }
 
890
            else if ((*(ptr + 1) == 'g') && (*(ptr + 2) == 't') && 
 
891
                     (*(ptr + 3) == ';'))
 
892
            {
 
893
                *buf << '>';
 
894
                ptr = ptr + 3;
 
895
            }
 
896
            else if ((*(ptr + 1) == 'q') && (*(ptr + 2) == 'u') && 
 
897
                     (*(ptr + 3) == 'o') && (*(ptr + 4) == 't') &&
 
898
                     (*(ptr + 5) == ';'))
 
899
            {
 
900
                *buf << '"';
 
901
                ptr = ptr + 5;
 
902
            }
 
903
            else if (*(ptr + 1) == 'a')
 
904
            {
 
905
                if ((*(ptr + 2) == 'm') && (*(ptr + 3) == 'p') && 
 
906
                    (*(ptr + 4) == ';'))
 
907
                    {
 
908
                        *buf << '&';
 
909
                        ptr = ptr + 4;
 
910
                    }
 
911
                else if ((*(ptr + 2) == 'p') && (*(ptr + 3) == 'o') &&
 
912
                         (*(ptr + 4) == 's') && (*(ptr + 5) == ';'))
 
913
                {
 
914
                    *buf << '\'';
 
915
                    ptr = ptr + 5;
 
916
                }
 
917
            }
 
918
            else
 
919
                *buf << *ptr;
 
920
        }
 
921
        else
 
922
            *buf << *ptr;
 
923
 
 
924
        ptr++;
 
925
    }
 
926
 
 
927
    return buf->toString();
 
928
}
 
929
*/
 
930
 
 
931
String unescape_amp(String string)
 
932
{
 
933
    if (string == nil)
 
934
        return nil;
 
935
    Ref<StringBase> stringBase(new StringBase(string.length()));
 
936
    char *str = stringBase->data;
 
937
    int len = string.length();
 
938
 
 
939
    int last = 0;
 
940
    do
 
941
    {
 
942
        int skip = 0;
 
943
        int next = last - 1;
 
944
        do
 
945
        {
 
946
            next = string.index(next + 1, '&');
 
947
            if ((next < len) && (string.charAt(next + 1) == 'a') && 
 
948
                (string.charAt(next + 2) == 'm') &&
 
949
                (string.charAt(next + 3) == 'p') &&
 
950
                (string.charAt(next + 4) == ';'))
 
951
            {
 
952
                skip = 4;
 
953
            }
 
954
        }
 
955
        while(next > 0 && skip == 0);
 
956
        
 
957
        if (next < 0)
 
958
            next = len;
 
959
        
 
960
        int cpLen = next - last + 1;
 
961
        strncpy(str, string.charPtrAt(last), cpLen);
 
962
        str += cpLen;
 
963
        last = next + skip + 1;
 
964
    }
 
965
    while (last <= len);
 
966
    
 
967
    stringBase->len = str - stringBase->data - 1;
 
968
    assert(stringBase->len == (int)strlen(stringBase->data));
 
969
    return String(stringBase);
 
970
}
 
971
 
 
972
String fallbackString(String first, String fallback)
 
973
{
 
974
    if (first==nil)
 
975
        return fallback;
 
976
    return first;
 
977
}
 
978
 
 
979
unsigned int stringHash(String str)
 
980
{
 
981
    unsigned int hash = 5381;
 
982
    unsigned char *data = (unsigned char *)str.c_str();
 
983
    int c;
 
984
    while ((c = *data++))
 
985
        hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
 
986
    return hash;
 
987
}
 
988
 
 
989
String intArrayToCSV(int *array, int size)
 
990
{
 
991
    if (size <= 0)
 
992
        return nil;
 
993
    Ref<StringBuffer> buf(new StringBuffer());
 
994
    for (int i = 0; i < size; i++)
 
995
        *buf << ',' << array[i];
 
996
    return buf->toString(1);
 
997
}
 
998
 
 
999
void getTimespecNow(struct timespec *ts)
 
1000
{
 
1001
    struct timeval tv;
 
1002
    int ret = gettimeofday(&tv, NULL);
 
1003
    if (ret != 0)
 
1004
        throw _Exception(_("gettimeofday failed: ") + mt_strerror(errno));
 
1005
    
 
1006
    ts->tv_sec = tv.tv_sec;
 
1007
    ts->tv_nsec = tv.tv_usec * 1000;
 
1008
}
 
1009
 
 
1010
long getDeltaMillis(struct timespec *first)
 
1011
{
 
1012
    struct timespec now;
 
1013
    getTimespecNow(&now);
 
1014
    return getDeltaMillis(first, &now);
 
1015
}
 
1016
 
 
1017
long getDeltaMillis(struct timespec *first, struct timespec *second)
 
1018
{
 
1019
    return (second->tv_sec - first->tv_sec) * 1000 + (second->tv_nsec - first->tv_nsec) / 1000000;
 
1020
}
 
1021
 
 
1022
void getTimespecAfterMillis(long delta, struct timespec *ret, struct timespec *start)
 
1023
{
 
1024
    struct timespec now;
 
1025
    if (start == NULL)
 
1026
    {
 
1027
        getTimespecNow(&now);
 
1028
        start = &now;
 
1029
    }
 
1030
    ret->tv_sec = start->tv_sec + delta / 1000;
 
1031
    ret->tv_nsec = (start->tv_nsec + (delta % 1000) * 1000000);
 
1032
    if (ret->tv_nsec >= 1000000000) // >= 1 second
 
1033
    {
 
1034
        ret->tv_sec ++;
 
1035
        ret->tv_nsec -= 1000000000;
 
1036
    }
 
1037
    
 
1038
    //log_debug("timespec: sec: %ld, nsec: %ld\n", ret->tv_sec, ret->tv_nsec);
 
1039
}
 
1040
 
 
1041
int compareTimespecs(struct timespec *a,  struct timespec *b)
 
1042
{
 
1043
    if (a->tv_sec < b->tv_sec)
 
1044
        return 1;
 
1045
    if (a->tv_sec > b->tv_sec)
 
1046
        return -1;
 
1047
    if (a->tv_nsec < b->tv_nsec)
 
1048
        return 1;
 
1049
    if (a->tv_nsec > b->tv_nsec)
 
1050
        return -1;
 
1051
    return 0;
 
1052
}
 
1053
 
 
1054
String normalizePath(String path)
 
1055
{
 
1056
    log_debug("Normalizing path: %s\n", path.c_str());
 
1057
    
 
1058
    int length = path.length();
 
1059
    
 
1060
    Ref<StringBase> result(new StringBase(length));
 
1061
    
 
1062
    int avarageExpectedSlashes = length/5;
 
1063
    if (avarageExpectedSlashes < 3)
 
1064
        avarageExpectedSlashes = 3;
 
1065
    Ref<BaseStack<int> > separatorLocations(new BaseStack<int>(avarageExpectedSlashes, -1));
 
1066
    char *str = result->data;
 
1067
    //int len = string.length();
 
1068
 
 
1069
#ifndef __CYGWIN__
 
1070
    if (path.charAt(0) != DIR_SEPARATOR)
 
1071
#else
 
1072
    #error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! this function is not finished for Cygwin
 
1073
    for (int i = 0; i < 20; i++)
 
1074
        print_backtrace();
 
1075
    /// \todo this doesn't seem to be correct...
 
1076
    if ((!path.length() > 1) && (path.charAt(1) != ':'))
 
1077
#endif
 
1078
        throw _Exception(_("Relative paths are not allowed!\n"));
 
1079
    
 
1080
    int next = 1;
 
1081
    do
 
1082
    {
 
1083
        while (next < length && path.charAt(next) == DIR_SEPARATOR)
 
1084
            next++;
 
1085
        if (next >= length)
 
1086
            break;
 
1087
        
 
1088
        int next_sep = path.index(next, DIR_SEPARATOR);
 
1089
        if (next_sep < 0)
 
1090
            next_sep = length;
 
1091
        if (next_sep == next + 1 && path.charAt(next) == '.')
 
1092
        {
 
1093
            //  "." - can be ignored
 
1094
        }
 
1095
        else if (next_sep == next + 2 &&
 
1096
            next + 1 < length &&
 
1097
            path.charAt(next) == '.' &&
 
1098
            path.charAt(next + 1) == '.')
 
1099
        {
 
1100
            // ".."
 
1101
            // go back one part
 
1102
            int lastSepLocation = separatorLocations->pop();
 
1103
            if (lastSepLocation < 0)
 
1104
                lastSepLocation = 0;
 
1105
            str = result->data + lastSepLocation;
 
1106
        }
 
1107
        else
 
1108
        {
 
1109
            // normal part
 
1110
            separatorLocations->push(str - result->data);
 
1111
            *(str++) = DIR_SEPARATOR;
 
1112
            int cpLen = next_sep - next;
 
1113
            strncpy(str, path.charPtrAt(next), cpLen);
 
1114
            str += cpLen;
 
1115
        }
 
1116
        next = next_sep + 1;
 
1117
    }
 
1118
    while(next < length);
 
1119
    
 
1120
    if (str == result->data)
 
1121
        *(str++) = DIR_SEPARATOR;
 
1122
    
 
1123
    *str = 0;
 
1124
    result->len = strlen(result->data);
 
1125
    return String(result);
 
1126
}
 
1127
 
 
1128
String interfaceToIP(String interface)
 
1129
{
 
1130
#if defined(__CYGWIN__)
 
1131
    struct hostent *h=NULL;
 
1132
    struct sockaddr_in LocalAddr;
 
1133
    char *hostname = (char *)MALLOC(256);
 
1134
    if (!hostname)
 
1135
        return nil;
 
1136
 
 
1137
    gethostname(hostname, 255);
 
1138
    hostname[255] = '\0';
 
1139
    h=gethostbyname(hostname);
 
1140
    free(hostname);
 
1141
    if (h != NULL)
 
1142
    {
 
1143
        memcpy(&LocalAddr.sin_addr, h->h_addr_list[0],4);
 
1144
        return String(inet_ntoa(LocalAddr.sin_addr));
 
1145
    }
 
1146
    return nil;
 
1147
#else
 
1148
 
 
1149
    struct if_nameindex *iflist = NULL;
 
1150
    struct if_nameindex *iflist_free = NULL;
 
1151
    struct ifreq if_request;
 
1152
    struct sockaddr_in local_address;
 
1153
    int local_socket;
 
1154
 
 
1155
    if (!string_ok(interface))
 
1156
            return nil;
 
1157
 
 
1158
    local_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
1159
    if (local_socket < 0)
 
1160
    {
 
1161
        log_error("Could not create local socket: %s\n", 
 
1162
                  mt_strerror(errno).c_str());
 
1163
        return nil;
 
1164
    }
 
1165
 
 
1166
    iflist = iflist_free = if_nameindex();
 
1167
    if (iflist == NULL)
 
1168
    {
 
1169
        log_error("Could not get interface list: %s\n", 
 
1170
                  mt_strerror(errno).c_str());
 
1171
        close(local_socket);
 
1172
        return nil;
 
1173
    }
 
1174
 
 
1175
    while (iflist->if_index || iflist->if_name)
 
1176
    {
 
1177
        if (interface == iflist->if_name)
 
1178
        {
 
1179
            strncpy(if_request.ifr_name, iflist->if_name, IF_NAMESIZE);
 
1180
            if (ioctl(local_socket, SIOCGIFADDR, &if_request) != 0)
 
1181
            {
 
1182
                log_error("Could not determine interface address: %s\n", 
 
1183
                          mt_strerror(errno).c_str());
 
1184
                close(local_socket);
 
1185
                if_freenameindex(iflist_free);
 
1186
                return nil;
 
1187
            }
 
1188
 
 
1189
            memcpy(&local_address, &if_request.ifr_addr, sizeof(if_request.ifr_addr));
 
1190
            String ip = inet_ntoa(local_address.sin_addr);
 
1191
            if_freenameindex(iflist_free);
 
1192
            close(local_socket);
 
1193
            return ip;
 
1194
        }
 
1195
        iflist++;
 
1196
    }
 
1197
 
 
1198
    close(local_socket);
 
1199
    if_freenameindex(iflist_free);
 
1200
    return nil;
 
1201
#endif
 
1202
}
 
1203
 
 
1204
bool validateYesNo(String value)
 
1205
{
 
1206
    if ((value != "yes") && (value != "no"))
 
1207
        return false;
 
1208
    else
 
1209
        return true;
 
1210
}
 
1211
 
 
1212
Ref<Array<StringBase> > parseCommandLine(String line, String in, String out)
 
1213
{
 
1214
    Ref<Array<StringBase> > params = split_string(line, ' ');
 
1215
    if ((in == nil) && (out == nil))
 
1216
        return params;
 
1217
 
 
1218
    for (int i = 0; i < params->size(); i++)
 
1219
    {
 
1220
        String param = params->get(i);
 
1221
        String newParam = param.replace(_("%in"), in);
 
1222
        newParam = newParam.replace(_("%out"), out);
 
1223
        if (param != newParam)
 
1224
            params->set(newParam, i);
 
1225
    }
 
1226
 
 
1227
    return params;
 
1228
}
 
1229
 
 
1230
// The tempName() function is borrowed from gfileutils.c from the glibc package
 
1231
 
 
1232
/* gfileutils.c - File utility functions
 
1233
 *
 
1234
 *  Copyright 2000 Red Hat, Inc.
 
1235
 *
 
1236
 * GLib is free software; you can redistribute it and/or modify it
 
1237
 * under the terms of the GNU Lesser General Public License as
 
1238
 * published by the Free Software Foundation; either version 2 of the
 
1239
 * License, or (at your option) any later version.
 
1240
 *
 
1241
 * GLib is distributed in the hope that it will be useful,
 
1242
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
1243
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
1244
 * Lesser General Public License for more details.
 
1245
 *
 
1246
 * You should have received a copy of the GNU Lesser General Public
 
1247
 * License along with GLib; see the file COPYING.LIB.  If not,
 
1248
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
1249
 *   Boston, MA 02111-1307, USA.
 
1250
 */
 
1251
/*
 
1252
 * create_temp_file based on the mkstemp implementation from the GNU C library.
 
1253
 * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
 
1254
 */
 
1255
// tempName is based on create_temp_file, see (C) above
 
1256
String tempName(String leadPath, char *tmpl)
 
1257
{
 
1258
    char *XXXXXX;
 
1259
    int count;
 
1260
    static const char letters[] =
 
1261
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 
1262
    static const int NLETTERS = sizeof (letters) - 1;
 
1263
    long value;
 
1264
    struct timeval tv;
 
1265
    static int counter = 0;
 
1266
    struct stat statbuf;
 
1267
    int ret = 0;
 
1268
 
 
1269
    /* find the last occurrence of "XXXXXX" */
 
1270
    XXXXXX = strstr (tmpl, "XXXXXX");
 
1271
 
 
1272
    if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
 
1273
    {
 
1274
        return nil;
 
1275
    }
 
1276
 
 
1277
    /* Get some more or less random data.  */
 
1278
    gettimeofday(&tv, NULL);
 
1279
    value = (tv.tv_usec ^ tv.tv_sec) + counter++;
 
1280
 
 
1281
    for (count = 0; count < 100; value += 7777, ++count)
 
1282
    {
 
1283
        long v = value;
 
1284
 
 
1285
        /* Fill in the random bits.  */
 
1286
        XXXXXX[0] = letters[v % NLETTERS];
 
1287
        v /= NLETTERS;
 
1288
        XXXXXX[1] = letters[v % NLETTERS];
 
1289
        v /= NLETTERS;
 
1290
        XXXXXX[2] = letters[v % NLETTERS];
 
1291
        v /= NLETTERS;
 
1292
        XXXXXX[3] = letters[v % NLETTERS];
 
1293
        v /= NLETTERS;
 
1294
        XXXXXX[4] = letters[v % NLETTERS];
 
1295
        v /= NLETTERS;
 
1296
        XXXXXX[5] = letters[v % NLETTERS];
 
1297
 
 
1298
        String check =  leadPath + tmpl;
 
1299
        ret = stat(check.c_str(), &statbuf);
 
1300
        if (ret != 0)
 
1301
        {
 
1302
            if ((errno == ENOENT) ||
 
1303
                    (errno == ENOTDIR))
 
1304
                return check;
 
1305
            else
 
1306
                return nil;
 
1307
        }
 
1308
    }
 
1309
 
 
1310
    /* We got out of the loop because we ran out of combinations to try.  */
 
1311
    return nil;
 
1312
}
 
1313
 
 
1314
bool isTheora(String ogg_filename)
 
1315
{
 
1316
    FILE *f;
 
1317
    char buffer[7];
 
1318
    f = fopen(ogg_filename.c_str(), "rb");
 
1319
 
 
1320
    if (!f)
 
1321
    {
 
1322
        throw _Exception(_("Error opening ") + ogg_filename + _(" : ") + 
 
1323
                    mt_strerror(errno));
 
1324
    }
 
1325
    
 
1326
    if (fread(buffer, 1, 4, f) != 4)
 
1327
    {
 
1328
        fclose(f);
 
1329
        throw _Exception(_("Error reading ") + ogg_filename);
 
1330
    }
 
1331
 
 
1332
    if (memcmp(buffer, "OggS", 4) != 0)
 
1333
    {
 
1334
        fclose(f);
 
1335
        return false;
 
1336
    }
 
1337
 
 
1338
    if (fseek(f, 28, SEEK_SET) != 0)
 
1339
    {
 
1340
        fclose(f);
 
1341
        throw _Exception(_("Incomplete file ") + ogg_filename);
 
1342
    }
 
1343
 
 
1344
    if (fread(buffer, 1, 7, f) != 7)
 
1345
    {
 
1346
        fclose(f);
 
1347
        throw _Exception(_("Error reading ") + ogg_filename);
 
1348
    }
 
1349
 
 
1350
    if (memcmp(buffer, "\x80theora", 7) != 0)
 
1351
    {
 
1352
        fclose(f);
 
1353
        return false;
 
1354
    }
 
1355
 
 
1356
    fclose(f);
 
1357
    return true;
 
1358
}
 
1359
 
 
1360
String get_last_path(String location)
 
1361
{
 
1362
    String path;
 
1363
 
 
1364
    int last_slash = location.rindex(DIR_SEPARATOR);
 
1365
    if (last_slash > 0)
 
1366
    {
 
1367
        path = location.substring(0, last_slash);
 
1368
        int slash = path.rindex(DIR_SEPARATOR);
 
1369
        if ((slash >= 0) && ((slash + 1) < path.length()))
 
1370
            path = path.substring(slash+1);
 
1371
    }
 
1372
 
 
1373
    return path;
 
1374
}
 
1375
 
 
1376
 
 
1377
ssize_t getValidUTF8CutPosition(zmm::String str, size_t cutpos)
 
1378
{
 
1379
    ssize_t pos = -1;
 
1380
    size_t len = str.length();
 
1381
 
 
1382
    if ((len == 0) || (cutpos > len))
 
1383
        return pos;
 
1384
 
 
1385
    printf("Character at cut position: %0x\n", (char)str.charAt(cutpos));
 
1386
    printf("Character at cut-1 position: %0x\n", (char)str.charAt(cutpos-1));
 
1387
    printf("Character at cut-2 position: %0x\n", (char)str.charAt(cutpos-2));
 
1388
    printf("Character at cut-3 position: %0x\n", (char)str.charAt(cutpos-3));
 
1389
 
 
1390
    // > 0x7f, we are dealing with a non-ascii character
 
1391
    if (str.charAt(cutpos) & 0x80)
 
1392
    {
 
1393
        // check if we are at byte 2
 
1394
        if (((cutpos-1) >= 0) && 
 
1395
             (((str.charAt(cutpos-1) & 0xc2) == 0xc2) ||
 
1396
              ((str.charAt(cutpos-1) & 0xe2) == 0xe2) ||
 
1397
              ((str.charAt(cutpos-1) & 0xf0) == 0xf0)))
 
1398
            pos = cutpos - 1;
 
1399
        // check if we are at byte 3
 
1400
        else if (((cutpos - 2) >= 0) && 
 
1401
                (((str.charAt(cutpos-2) & 0xe2) == 0xe2) ||
 
1402
                 ((str.charAt(cutpos-2) & 0xf0) == 0xf0)))
 
1403
            pos = cutpos - 2;
 
1404
        // we must be at byte 4 then...
 
1405
        else if ((cutpos - 3) >= 0)
 
1406
            pos = cutpos - 3;
 
1407
    }
 
1408
    else
 
1409
        pos = cutpos;
 
1410
 
 
1411
    return pos;
 
1412
}
 
1413
 
 
1414
#ifdef EXTEND_PROTOCOLINFO
 
1415
String getDLNAtransferHeader(String mimeType, String header)
 
1416
{
 
1417
        if (ConfigManager::getInstance()->getBoolOption(CFG_SERVER_EXTEND_PROTOCOLINFO))
 
1418
        {
 
1419
            String transfer_parameter;
 
1420
            if (mimeType.startsWith(_("image")))
 
1421
                transfer_parameter = _(D_HTTP_TRANSFER_MODE_INTERACTIVE);
 
1422
            else if (mimeType.startsWith(_("audio")) ||
 
1423
                     mimeType.startsWith(_("video")))
 
1424
                transfer_parameter = _(D_HTTP_TRANSFER_MODE_STREAMING);
 
1425
 
 
1426
            if (string_ok(transfer_parameter))
 
1427
            {
 
1428
                if (string_ok(header))
 
1429
                    header = header + _("\r\n");
 
1430
 
 
1431
                header = header + D_HTTP_TRANSFER_MODE_HEADER +
 
1432
                         transfer_parameter;
 
1433
            }
 
1434
        }
 
1435
 
 
1436
    return header;
 
1437
}
 
1438
#endif
 
1439
 
 
1440
#ifndef HAVE_FFMPEG
 
1441
String getAVIFourCC(zmm::String avi_filename)
 
1442
{
 
1443
#define FCC_OFFSET  0xbc
 
1444
    char *buffer;
 
1445
    FILE *f = fopen(avi_filename.c_str(), "rb");
 
1446
    if (!f)
 
1447
        throw _Exception(_("could not open file ") + avi_filename + " : " +
 
1448
                          mt_strerror(errno));
 
1449
 
 
1450
    buffer = (char *)MALLOC(FCC_OFFSET+6);
 
1451
    if (buffer == NULL)
 
1452
    {
 
1453
        fclose(f);
 
1454
        throw _Exception(_("Out of memory when allocating buffer for file ") +
 
1455
                          avi_filename);
 
1456
    }
 
1457
 
 
1458
    size_t rb = fread(buffer, 1, FCC_OFFSET+4, f);
 
1459
    fclose(f);
 
1460
    if (rb != FCC_OFFSET+4)
 
1461
    {
 
1462
        free(buffer);
 
1463
        throw _Exception(_("could not read header of ") + avi_filename +  
 
1464
                          " : " + mt_strerror(errno));
 
1465
    }
 
1466
 
 
1467
    buffer[FCC_OFFSET+5] = '\0';
 
1468
 
 
1469
    if (strncmp(buffer, "RIFF", 4) != 0)
 
1470
    {
 
1471
        free(buffer);
 
1472
        return nil;
 
1473
    }
 
1474
 
 
1475
    if (strncmp(buffer+8, "AVI ", 4) != 0)
 
1476
    {
 
1477
        free(buffer);
 
1478
        return nil;
 
1479
    }
 
1480
 
 
1481
    String fourcc = String(buffer+FCC_OFFSET, 4);
 
1482
    free(buffer);
 
1483
 
 
1484
    if (string_ok(fourcc))
 
1485
        return fourcc;
 
1486
    else
 
1487
        return nil;
 
1488
}
 
1489
#endif
 
1490
 
 
1491
#ifdef TOMBDEBUG
 
1492
 
 
1493
void profiling_thread_check(struct profiling_t *data)
 
1494
{
 
1495
    if (data->thread != pthread_self())
 
1496
    {
 
1497
        log_debug("profiling_..() called from a different thread than profiling_init was called! (init: %d; this: %d) - aborting...\n", data->thread, pthread_self());
 
1498
        print_backtrace();
 
1499
        abort();
 
1500
        return;
 
1501
    }
 
1502
}
 
1503
 
 
1504
 
 
1505
void profiling_start(struct profiling_t *data)
 
1506
{
 
1507
    profiling_thread_check(data);
 
1508
    if (data->running)
 
1509
    {
 
1510
        log_debug("profiling_start() called on an already running profile! - aborting...\n");
 
1511
        print_backtrace();
 
1512
        abort();
 
1513
        return;
 
1514
    }
 
1515
    data->running = true;
 
1516
    getTimespecNow(&(data->last_start));
 
1517
}
 
1518
 
 
1519
void profiling_end(struct profiling_t *data)
 
1520
{
 
1521
    profiling_thread_check(data);
 
1522
    struct timespec now;
 
1523
    getTimespecNow(&now);
 
1524
    if (! data->running)
 
1525
    {
 
1526
        log_debug("profiling_end() called on a not-running profile! - aborting...\n");
 
1527
        print_backtrace();
 
1528
        abort();
 
1529
        return;
 
1530
    }
 
1531
    struct timespec *sum = &(data->sum);
 
1532
    struct timespec *last_start = &(data->last_start);
 
1533
    sum->tv_sec += now.tv_sec - last_start->tv_sec;
 
1534
    //log_debug("!!!!!! adding %d sec\n", now.tv_sec - last_start->tv_sec);
 
1535
    if (now.tv_nsec >= last_start->tv_nsec)
 
1536
    {
 
1537
        sum->tv_nsec += now.tv_nsec - last_start->tv_nsec;
 
1538
        //log_debug("adding %ld nsec\n", now.tv_nsec - last_start->tv_nsec);
 
1539
    }
 
1540
    else
 
1541
    {
 
1542
        sum->tv_nsec += 1000000000L - last_start->tv_nsec + now.tv_nsec;
 
1543
        sum->tv_sec --;
 
1544
    }
 
1545
    if(sum->tv_nsec >= 1000000000L)
 
1546
    {
 
1547
        sum->tv_nsec -= 1000000000L;
 
1548
        sum->tv_sec ++;
 
1549
    }
 
1550
    
 
1551
    data->running = false;
 
1552
}
 
1553
 
 
1554
void profiling_print(struct profiling_t *data)
 
1555
{
 
1556
    if (data->running)
 
1557
    {
 
1558
        log_debug("profiling_print() called on running profile! - aborting...\n");
 
1559
        print_backtrace();
 
1560
        abort();
 
1561
        return;
 
1562
    }
 
1563
    //log_debug("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nPROFILING: took %ld sec %ld nsec thread %u\n", data->sum.tv_sec, data->sum.tv_nsec, pthread_self());
 
1564
    log_debug("PROFILING: took %ld sec %ld nsec\n", data->sum.tv_sec, data->sum.tv_nsec);
 
1565
}
 
1566
 
 
1567
#endif
 
1568
 
 
1569
#ifdef SOPCAST
 
1570
/// \brief 
 
1571
int find_local_port(unsigned short range_min, unsigned short range_max)
 
1572
{
 
1573
    int fd;
 
1574
    int retry_count = 0;
 
1575
    int port;
 
1576
    struct sockaddr_in server_addr;
 
1577
    struct hostent *server;
 
1578
 
 
1579
    if (range_min > range_max)
 
1580
    {
 
1581
        log_error("min port range > max port range!\n");
 
1582
        return -1;
 
1583
    }
 
1584
 
 
1585
    
 
1586
    do
 
1587
    {
 
1588
        port =  rand () % (range_max - range_min) + range_min;
 
1589
 
 
1590
        fd = socket(AF_INET, SOCK_STREAM, 0);
 
1591
        if (fd < 0)
 
1592
        {
 
1593
            log_error("could not determine free port: "
 
1594
                      "error creating socket (%s)\n", mt_strerror(errno).c_str());
 
1595
            return -1;
 
1596
        }
 
1597
 
 
1598
        server = gethostbyname("127.0.0.1");
 
1599
        if (server == NULL)
 
1600
        {
 
1601
            log_error("could not resolve localhost\n");
 
1602
            close(fd);
 
1603
            return -1;
 
1604
        }
 
1605
 
 
1606
        memset(&server_addr, 0, sizeof(server_addr));
 
1607
        server_addr.sin_family = AF_INET;
 
1608
        memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);
 
1609
        server_addr.sin_port = htons(port);
 
1610
 
 
1611
        if (connect(fd, (struct sockaddr *)&server_addr, 
 
1612
            sizeof(server_addr)) == -1)
 
1613
        {
 
1614
            close(fd);
 
1615
            return port;
 
1616
        }
 
1617
 
 
1618
        retry_count++;
 
1619
 
 
1620
    } while (retry_count < USHRT_MAX);
 
1621
 
 
1622
    log_error("Could not find free port on localhost\n");
 
1623
 
 
1624
    return -1;
 
1625
}
 
1626
#endif