~vanvugt/+junk/mediatomb

« back to all changes in this revision

Viewing changes to .pc/const_char_conversion.patch/src/tools.cc

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Le Folgoc
  • Date: 2010-02-22 20:16:31 UTC
  • mfrom: (4.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100222201631-fgwswo4s4ogdr8x8
Tags: 0.12.0~svn2018-6ubuntu1
* Merge from debian unstable, Ubuntu remaining changes:
  - Add OR depends on abrowser.

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