3
MediaTomb - http://www.mediatomb.cc/
5
tools.cc - this file is part of MediaTomb.
7
Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
8
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
10
Copyright (C) 2006-2010 Gena Batyan <bgeradz@mediatomb.cc>,
11
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
12
Leonhard Wimmer <leo@mediatomb.cc>
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.
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.
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.
27
$Id: tools.cc 2081 2010-03-23 20:18:00Z lww $
33
#include "autoconfig.h"
40
#include <sys/ioctl.h>
41
#include <sys/socket.h>
42
#include <netinet/in.h>
43
#include <arpa/inet.h>
47
#include "config_manager.h"
54
#include <sys/sockio.h>
58
#include "file_io_handler.h"
59
#include "metadata_handler.h"
61
#define WHITE_SPACE " \t\r\n"
65
static const char *HEX_CHARS = "0123456789abcdef";
67
Ref<Array<StringBase> > split_string(String str, char sep, bool empty)
69
Ref<Array<StringBase> > ret(new Array<StringBase>());
70
char *data = str.c_str();
71
char *end = data + str.length();
74
char *pos = strchr(data, sep);
84
if ((data < end) && empty)
89
String part(data, pos - data);
97
Ref<Array<StringBase> > split_path(String 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();
106
throw _Exception(_("relative path given to split_path: ") + str);
110
/* there is only one separator at the beginning "/..." or "/" */
111
ret->append(_(_DIR_SEPARATOR));
112
String filename = data + 1;
113
ret->append(filename);
117
String path(data, pos);
119
String filename = data + pos + 1;
120
ret->append(filename);
125
String trim_string(String str)
132
int len = str.length();
134
char *buf = str.c_str();
136
for (i = 0; i < len; i++)
138
if (! strchr(WHITE_SPACE, buf[i]))
146
for (i = len - 1; i >= start; i--)
148
if (! strchr(WHITE_SPACE, buf[i]))
154
return str.substring(start, end - start);
157
bool check_path(String path, bool needDir)
162
ret = stat(path.c_str(), &statbuf);
163
if (ret != 0) return false;
165
if ((needDir && (!S_ISDIR(statbuf.st_mode))) ||
166
(!needDir && (S_ISDIR(statbuf.st_mode)))) return false;
171
time_t check_path_ex(String path, bool needDir, bool existenceUnneeded,
177
if (filesize != NULL)
180
ret = stat(path.c_str(), &statbuf);
183
if (existenceUnneeded && (errno == ENOENT))
186
throw _Exception(path + " : " + errno + (int)existenceUnneeded+ " x " + mt_strerror(errno));
189
if (needDir && (!S_ISDIR(statbuf.st_mode)))
190
throw _Exception(_("Not a directory: ") + path);
192
if (!needDir && (S_ISDIR(statbuf.st_mode)))
193
throw _Exception(_("Not a file: ") + path);
195
if ((filesize != NULL) && S_ISREG(statbuf.st_mode))
196
*filesize = statbuf.st_size;
198
return statbuf.st_mtime;
201
bool is_executable(String path, int *err)
203
int ret = access(path.c_str(), R_OK | X_OK);
213
String find_in_path(String exec)
215
String PATH = getenv("PATH");
216
if (!string_ok(PATH))
219
Ref<StringTokenizer> st(new StringTokenizer(PATH));
225
path = st->nextToken(_(":"));
226
next = st->nextToken(_(":"));
231
if ((next != nil) && !next.startsWith(_("/")))
233
path = path + _(":") + next;
237
String check = path + _("/") + exec;
238
if (check_path(check))
247
} while (path != nil);
252
bool string_ok(String str)
254
if ((str == nil) || (str == ""))
259
bool string_ok(Ref<StringBuffer> str)
262
if ((str == nil) || (str->length()<=0))
268
void string_ok_ex(String str)
270
if ((str == nil) || (str == ""))
271
throw _Exception(_("Empty string"));
274
String http_redirect_to(String ip, String port, String page)
276
return _("<html><head><meta http-equiv=\"Refresh\" content=\"0;URL=http://") + ip + ":" + port + "/" + page + "\"></head><body bgcolor=\"#dddddd\"></body></html>";
279
String hex_encode(void *data, int len)
281
unsigned char *chars;
283
unsigned char hi, lo;
285
Ref<StringBuffer> buf(new StringBuffer(len * 2));
287
chars = (unsigned char *)data;
288
for (i = 0; i < len; i++)
290
unsigned char c = chars[i];
293
*buf << HEX_CHARS[hi] << HEX_CHARS[lo];
295
return buf->toString();
299
String hex_decode_string(String encoded)
301
char *ptr = encoded.c_str();
302
int len = encoded.length();
304
Ref<StringBuffer> buf(new StringBuffer(len / 2));
305
for (int i = 0; i < len; i += 2)
307
const char *chi = strchr(HEX_CHARS, ptr[i]);
308
const char *clo = strchr(HEX_CHARS, ptr[i + 1]);
312
hi = chi - HEX_CHARS;
317
lo = clo - HEX_CHARS;
320
char ch = (char)(hi << 4 | lo);
323
return buf->toString();
331
String hex_md5(void *data, int length)
337
md5_append(&ctx, (unsigned char *)data, length);
338
md5_finish(&ctx, (unsigned char *)md5buf);
340
return hex_encode(md5buf, 16);
342
String hex_string_md5(String str)
344
return hex_md5(str.c_str(), str.length());
346
String generate_random_id()
348
struct randomizer st;
349
gettimeofday(&st.tv, NULL);
351
return hex_md5(&st, sizeof(st));
355
static const char *hex = "0123456789ABCDEF";
357
String url_escape(String str)
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++)
364
unsigned char c = (unsigned char)data[i];
365
if ((c >= '0' && c <= '9') ||
366
(c >= 'A' && c <= 'Z') ||
367
(c >= 'a' && c <= 'z') ||
377
*buf << '%' << hex[hi] << hex[lo];
380
return buf->toString();
383
String url_unescape(String str)
385
char *data = str.c_str();
386
int len = str.length();
387
Ref<StringBuffer> buf(new StringBuffer(len));
396
break; // avoid buffer overrun
397
char chi = data[i++];
398
char clo = data[i++];
403
pos = strchr(hex, chi);
409
pos = strchr(hex, clo);
415
int ascii = (hi << 4) | lo;
427
return buf->toString();
430
String mime_types_to_CSV(Ref<Array<StringBase> > mimeTypes)
432
Ref<StringBuffer> buf(new StringBuffer());
433
for (int i = 0; i < mimeTypes->size(); i++)
437
String mimeType = mimeTypes->get(i);
438
*buf << "http-get:*:" << mimeType << ":*";
441
return buf->toString();
444
String mt_strerror(int mt_errno)
446
#ifdef DONT_USE_YET_HAVE_STRERROR_R
447
char *buffer = (char *)MALLOC(512);
449
#ifdef STRERROR_R_CHAR_P
450
err_str = strerror_r(errno, buffer, 512);
454
int ret = strerror_r(errno, buffer, 512);
456
return _("cannot get error string: error while calling XSI-compliant strerror_r");
459
String errStr(err_str);
463
return strerror(errno);
467
String read_text_file(String path)
469
FILE *f = fopen(path.c_str(), "r");
472
throw _Exception(_("read_text_file: could not open ") +
473
path + " : " + mt_strerror(errno));
475
Ref<StringBuffer> buf(new StringBuffer());
476
char *buffer = (char *)MALLOC(1024);
478
while((bytesRead = fread(buffer, 1, 1024, f)) > 0)
480
buf->concat(buffer, bytesRead);
484
return buf->toString();
486
void write_text_file(String path, String contents)
489
FILE *f = fopen(path.c_str(), "w");
492
throw _Exception(_("write_text_file: could not open ") +
493
path + " : " + mt_strerror(errno));
496
bytesWritten = fwrite(contents.c_str(), 1, contents.length(), f);
497
if (bytesWritten < contents.length())
500
if (bytesWritten >= 0)
501
throw _Exception(_("write_text_file: incomplete write to ") +
504
throw _Exception(_("write_text_file: error writing to ") +
505
path + " : " + mt_strerror(errno));
510
void copy_file(String from, String to)
512
FILE *f = fopen(from.c_str(), "r");
515
throw _Exception(_("copy_file: could not open ") +
516
from + " for read: " + mt_strerror(errno));
518
FILE *t = fopen(to.c_str(), "w");
522
throw _Exception(_("copy_file: could not open ") +
523
to + " for write: " + mt_strerror(errno));
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)
531
bytesWritten = fwrite(buffer, 1, bytesRead, t);
534
if (ferror(f) || ferror(t))
536
int my_errno = errno;
539
throw _Exception(_("copy_file: error while copying ") + from + " to " +
540
to + ": " + mt_strerror(my_errno));
548
int StringBaseComparator(void *arg1, void *arg2)
550
return strcmp(((StringBase *)arg1)->data, ((StringBase *)arg2)->data);
553
static void quicksort_impl(COMPARABLE *a, int lo0, int hi0, COMPARATOR comparator)
562
// sort a two element list by swapping if necessary
563
// if (a[lo] > a[hi])
564
if (comparator(a[lo], a[hi]) > 0)
566
COMPARABLE T = a[lo];
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];
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)
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)
596
/* Swap elements a[lo] and a[hi] */
599
COMPARABLE T = a[lo];
605
/* Put the median in the "center" of the list */
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
614
quicksort_impl(a, lo0, lo-1, comparator);
615
quicksort_impl(a, hi+1, hi0, comparator);
618
void quicksort(COMPARABLE *arr, int size, COMPARATOR comparator)
620
quicksort_impl(arr, 0, size - 1, comparator);
623
String renderProtocolInfo(String mimetype, String protocol, String extend)
625
if (string_ok(mimetype) && string_ok(protocol))
627
if (string_ok(extend))
628
return protocol + ":*:" + mimetype + ":" + extend;
630
return protocol + ":*:" + mimetype + ":*";
633
return _("http-get:*:*:*");
636
String getMTFromProtocolInfo(String protocol)
638
Ref<Array<StringBase> > parts = split_string(protocol, ':');
639
if (parts->size() > 2)
640
return parts->get(2);
645
String getProtocol(String protocolInfo)
648
int pos = protocolInfo.index(':');
650
protocol = _("http-get");
652
protocol = protocolInfo.substring(0, pos);
657
String secondsToHMS(int seconds)
668
char *str = (char *)malloc(10);
669
sprintf(str, "%02d:%02d:%02d", h, m, s);
670
return String::take(str);
673
int HMSToSeconds(String time)
675
if (!string_ok(time))
677
log_warning("Could not convert time representation to seconds!\n");
684
sscanf(time.c_str(), "%d:%d:%d", &hours, &minutes, &seconds);
686
return (hours * 3600) + (minutes * 60) + seconds;
690
String get_mime_type(magic_set *ms, Ref<RExp> reMimetype, String file)
695
char *mt = (char *)magic_file(ms, file.c_str());
698
log_error("magic_file: %s\n", magic_error(ms));
702
String mime_type = mt;
704
Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
706
return matcher->group(1);
708
log_warning("filemagic returned invalid mimetype for %s\n%s\n",
713
String get_mime_type_from_buffer(magic_set *ms, Ref<RExp> reMimetype,
714
void *buffer, size_t length)
719
char *mt = (char *)magic_buffer(ms, buffer, length);
722
log_error("magic_file: %s\n", magic_error(ms));
726
String mime_type = mt;
728
Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
730
return matcher->group(1);
732
log_warning("filemagic returned invalid mimetype for the given buffer%s\n",
738
void set_jpeg_resolution_resource(Ref<CdsItem> item, int res_num)
742
Ref<IOHandler> fio_h(new FileIOHandler(item->getLocation()));
743
fio_h->open(UPNP_READ);
744
String resolution = get_jpeg_resolution(fio_h);
746
if (res_num >= item->getResourceCount())
747
throw _Exception(_("Invalid resource index"));
749
item->getResource(res_num)->addAttribute(MetadataHandler::getResAttrName(R_RESOLUTION), resolution);
757
bool check_resolution(String resolution, int *x, int *y)
765
Ref<Array<StringBase> > parts = split_string(resolution, 'x');
766
if (parts->size() != 2)
769
if (string_ok(parts->get(0)) &&
770
string_ok(parts->get(1)))
772
int _x = _(parts->get(0)->data).toInt();
773
int _y = _(parts->get(1)->data).toInt();
775
if ((_x > 0) && (_y > 0))
791
String escape(String string, char escape_char, char to_escape)
793
Ref<StringBase> stringBase(new StringBase(string.length() * 2));
794
char *str = stringBase->data;
795
int len = string.length();
797
bool possible_more_esc = true;
798
bool possible_more_char = true;
804
if (possible_more_esc)
806
next_esc = string.index(last, escape_char);
808
possible_more_esc = false;
812
if (possible_more_char)
814
next = string.index(last, to_escape);
816
possible_more_char = false;
819
if (next < 0 || (next_esc >= 0 && next_esc < next))
826
int cpLen = next - last;
829
strncpy(str, string.charPtrAt(last), cpLen);
835
*(str++) = string.charAt(next);
843
stringBase->len = strlen(stringBase->data);
844
return stringBase->data;
847
String unescape(String string, char escape)
849
Ref<StringBase> stringBase(new StringBase(string.length()));
850
char *str = stringBase->data;
851
int len = string.length();
856
int next = string.index(last + 1, escape);
861
int cpLen = next - last;
863
strncpy(str, string.charPtrAt(last), cpLen);
871
stringBase->len = strlen(stringBase->data);
872
return String(stringBase);
876
String xml_unescape(String string)
878
Ref<StringBuffer> buf(new StringBuffer(string.length()));
879
signed char *ptr = (signed char *)string.c_str();
884
if ((*(ptr + 1) == 'l') && (*(ptr + 2) == 't') &&
890
else if ((*(ptr + 1) == 'g') && (*(ptr + 2) == 't') &&
896
else if ((*(ptr + 1) == 'q') && (*(ptr + 2) == 'u') &&
897
(*(ptr + 3) == 'o') && (*(ptr + 4) == 't') &&
903
else if (*(ptr + 1) == 'a')
905
if ((*(ptr + 2) == 'm') && (*(ptr + 3) == 'p') &&
911
else if ((*(ptr + 2) == 'p') && (*(ptr + 3) == 'o') &&
912
(*(ptr + 4) == 's') && (*(ptr + 5) == ';'))
927
return buf->toString();
931
String unescape_amp(String string)
935
Ref<StringBase> stringBase(new StringBase(string.length()));
936
char *str = stringBase->data;
937
int len = string.length();
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) == ';'))
955
while(next > 0 && skip == 0);
960
int cpLen = next - last + 1;
961
strncpy(str, string.charPtrAt(last), cpLen);
963
last = next + skip + 1;
967
stringBase->len = str - stringBase->data - 1;
968
assert(stringBase->len == (int)strlen(stringBase->data));
969
return String(stringBase);
972
String fallbackString(String first, String fallback)
979
unsigned int stringHash(String str)
981
unsigned int hash = 5381;
982
unsigned char *data = (unsigned char *)str.c_str();
984
while ((c = *data++))
985
hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
989
String intArrayToCSV(int *array, int size)
993
Ref<StringBuffer> buf(new StringBuffer());
994
for (int i = 0; i < size; i++)
995
*buf << ',' << array[i];
996
return buf->toString(1);
999
void getTimespecNow(struct timespec *ts)
1002
int ret = gettimeofday(&tv, NULL);
1004
throw _Exception(_("gettimeofday failed: ") + mt_strerror(errno));
1006
ts->tv_sec = tv.tv_sec;
1007
ts->tv_nsec = tv.tv_usec * 1000;
1010
long getDeltaMillis(struct timespec *first)
1012
struct timespec now;
1013
getTimespecNow(&now);
1014
return getDeltaMillis(first, &now);
1017
long getDeltaMillis(struct timespec *first, struct timespec *second)
1019
return (second->tv_sec - first->tv_sec) * 1000 + (second->tv_nsec - first->tv_nsec) / 1000000;
1022
void getTimespecAfterMillis(long delta, struct timespec *ret, struct timespec *start)
1024
struct timespec now;
1027
getTimespecNow(&now);
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
1035
ret->tv_nsec -= 1000000000;
1038
//log_debug("timespec: sec: %ld, nsec: %ld\n", ret->tv_sec, ret->tv_nsec);
1041
int compareTimespecs(struct timespec *a, struct timespec *b)
1043
if (a->tv_sec < b->tv_sec)
1045
if (a->tv_sec > b->tv_sec)
1047
if (a->tv_nsec < b->tv_nsec)
1049
if (a->tv_nsec > b->tv_nsec)
1054
String normalizePath(String path)
1056
log_debug("Normalizing path: %s\n", path.c_str());
1058
int length = path.length();
1060
Ref<StringBase> result(new StringBase(length));
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();
1070
if (path.charAt(0) != DIR_SEPARATOR)
1072
#error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! this function is not finished for Cygwin
1073
for (int i = 0; i < 20; i++)
1075
/// \todo this doesn't seem to be correct...
1076
if ((!path.length() > 1) && (path.charAt(1) != ':'))
1078
throw _Exception(_("Relative paths are not allowed!\n"));
1083
while (next < length && path.charAt(next) == DIR_SEPARATOR)
1088
int next_sep = path.index(next, DIR_SEPARATOR);
1091
if (next_sep == next + 1 && path.charAt(next) == '.')
1093
// "." - can be ignored
1095
else if (next_sep == next + 2 &&
1096
next + 1 < length &&
1097
path.charAt(next) == '.' &&
1098
path.charAt(next + 1) == '.')
1102
int lastSepLocation = separatorLocations->pop();
1103
if (lastSepLocation < 0)
1104
lastSepLocation = 0;
1105
str = result->data + lastSepLocation;
1110
separatorLocations->push(str - result->data);
1111
*(str++) = DIR_SEPARATOR;
1112
int cpLen = next_sep - next;
1113
strncpy(str, path.charPtrAt(next), cpLen);
1116
next = next_sep + 1;
1118
while(next < length);
1120
if (str == result->data)
1121
*(str++) = DIR_SEPARATOR;
1124
result->len = strlen(result->data);
1125
return String(result);
1128
String interfaceToIP(String interface)
1130
#if defined(__CYGWIN__)
1131
struct hostent *h=NULL;
1132
struct sockaddr_in LocalAddr;
1133
char *hostname = (char *)MALLOC(256);
1137
gethostname(hostname, 255);
1138
hostname[255] = '\0';
1139
h=gethostbyname(hostname);
1143
memcpy(&LocalAddr.sin_addr, h->h_addr_list[0],4);
1144
return String(inet_ntoa(LocalAddr.sin_addr));
1149
struct if_nameindex *iflist = NULL;
1150
struct if_nameindex *iflist_free = NULL;
1151
struct ifreq if_request;
1152
struct sockaddr_in local_address;
1155
if (!string_ok(interface))
1158
local_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1159
if (local_socket < 0)
1161
log_error("Could not create local socket: %s\n",
1162
mt_strerror(errno).c_str());
1166
iflist = iflist_free = if_nameindex();
1169
log_error("Could not get interface list: %s\n",
1170
mt_strerror(errno).c_str());
1171
close(local_socket);
1175
while (iflist->if_index || iflist->if_name)
1177
if (interface == iflist->if_name)
1179
strncpy(if_request.ifr_name, iflist->if_name, IF_NAMESIZE);
1180
if (ioctl(local_socket, SIOCGIFADDR, &if_request) != 0)
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);
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);
1198
close(local_socket);
1199
if_freenameindex(iflist_free);
1204
bool validateYesNo(String value)
1206
if ((value != "yes") && (value != "no"))
1212
Ref<Array<StringBase> > parseCommandLine(String line, String in, String out)
1214
Ref<Array<StringBase> > params = split_string(line, ' ');
1215
if ((in == nil) && (out == nil))
1218
for (int i = 0; i < params->size(); i++)
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);
1230
// The tempName() function is borrowed from gfileutils.c from the glibc package
1232
/* gfileutils.c - File utility functions
1234
* Copyright 2000 Red Hat, Inc.
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.
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.
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.
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.
1255
// tempName is based on create_temp_file, see (C) above
1256
String tempName(String leadPath, char *tmpl)
1260
static const char letters[] =
1261
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1262
static const int NLETTERS = sizeof (letters) - 1;
1265
static int counter = 0;
1266
struct stat statbuf;
1269
/* find the last occurrence of "XXXXXX" */
1270
XXXXXX = strstr (tmpl, "XXXXXX");
1272
if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
1277
/* Get some more or less random data. */
1278
gettimeofday(&tv, NULL);
1279
value = (tv.tv_usec ^ tv.tv_sec) + counter++;
1281
for (count = 0; count < 100; value += 7777, ++count)
1285
/* Fill in the random bits. */
1286
XXXXXX[0] = letters[v % NLETTERS];
1288
XXXXXX[1] = letters[v % NLETTERS];
1290
XXXXXX[2] = letters[v % NLETTERS];
1292
XXXXXX[3] = letters[v % NLETTERS];
1294
XXXXXX[4] = letters[v % NLETTERS];
1296
XXXXXX[5] = letters[v % NLETTERS];
1298
String check = leadPath + tmpl;
1299
ret = stat(check.c_str(), &statbuf);
1302
if ((errno == ENOENT) ||
1310
/* We got out of the loop because we ran out of combinations to try. */
1314
bool isTheora(String ogg_filename)
1318
f = fopen(ogg_filename.c_str(), "rb");
1322
throw _Exception(_("Error opening ") + ogg_filename + _(" : ") +
1323
mt_strerror(errno));
1326
if (fread(buffer, 1, 4, f) != 4)
1329
throw _Exception(_("Error reading ") + ogg_filename);
1332
if (memcmp(buffer, "OggS", 4) != 0)
1338
if (fseek(f, 28, SEEK_SET) != 0)
1341
throw _Exception(_("Incomplete file ") + ogg_filename);
1344
if (fread(buffer, 1, 7, f) != 7)
1347
throw _Exception(_("Error reading ") + ogg_filename);
1350
if (memcmp(buffer, "\x80theora", 7) != 0)
1360
String get_last_path(String location)
1364
int last_slash = location.rindex(DIR_SEPARATOR);
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);
1377
ssize_t getValidUTF8CutPosition(zmm::String str, size_t cutpos)
1380
size_t len = str.length();
1382
if ((len == 0) || (cutpos > len))
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));
1390
// > 0x7f, we are dealing with a non-ascii character
1391
if (str.charAt(cutpos) & 0x80)
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)))
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)))
1404
// we must be at byte 4 then...
1405
else if ((cutpos - 3) >= 0)
1414
#ifdef EXTEND_PROTOCOLINFO
1415
String getDLNAtransferHeader(String mimeType, String header)
1417
if (ConfigManager::getInstance()->getBoolOption(CFG_SERVER_EXTEND_PROTOCOLINFO))
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);
1426
if (string_ok(transfer_parameter))
1428
if (string_ok(header))
1429
header = header + _("\r\n");
1431
header = header + D_HTTP_TRANSFER_MODE_HEADER +
1441
String getAVIFourCC(zmm::String avi_filename)
1443
#define FCC_OFFSET 0xbc
1445
FILE *f = fopen(avi_filename.c_str(), "rb");
1447
throw _Exception(_("could not open file ") + avi_filename + " : " +
1448
mt_strerror(errno));
1450
buffer = (char *)MALLOC(FCC_OFFSET+6);
1454
throw _Exception(_("Out of memory when allocating buffer for file ") +
1458
size_t rb = fread(buffer, 1, FCC_OFFSET+4, f);
1460
if (rb != FCC_OFFSET+4)
1463
throw _Exception(_("could not read header of ") + avi_filename +
1464
" : " + mt_strerror(errno));
1467
buffer[FCC_OFFSET+5] = '\0';
1469
if (strncmp(buffer, "RIFF", 4) != 0)
1475
if (strncmp(buffer+8, "AVI ", 4) != 0)
1481
String fourcc = String(buffer+FCC_OFFSET, 4);
1484
if (string_ok(fourcc))
1493
void profiling_thread_check(struct profiling_t *data)
1495
if (data->thread != pthread_self())
1497
log_debug("profiling_..() called from a different thread than profiling_init was called! (init: %d; this: %d) - aborting...\n", data->thread, pthread_self());
1505
void profiling_start(struct profiling_t *data)
1507
profiling_thread_check(data);
1510
log_debug("profiling_start() called on an already running profile! - aborting...\n");
1515
data->running = true;
1516
getTimespecNow(&(data->last_start));
1519
void profiling_end(struct profiling_t *data)
1521
profiling_thread_check(data);
1522
struct timespec now;
1523
getTimespecNow(&now);
1524
if (! data->running)
1526
log_debug("profiling_end() called on a not-running profile! - aborting...\n");
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)
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);
1542
sum->tv_nsec += 1000000000L - last_start->tv_nsec + now.tv_nsec;
1545
if(sum->tv_nsec >= 1000000000L)
1547
sum->tv_nsec -= 1000000000L;
1551
data->running = false;
1554
void profiling_print(struct profiling_t *data)
1558
log_debug("profiling_print() called on running profile! - aborting...\n");
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);
1571
int find_local_port(unsigned short range_min, unsigned short range_max)
1574
int retry_count = 0;
1576
struct sockaddr_in server_addr;
1577
struct hostent *server;
1579
if (range_min > range_max)
1581
log_error("min port range > max port range!\n");
1588
port = rand () % (range_max - range_min) + range_min;
1590
fd = socket(AF_INET, SOCK_STREAM, 0);
1593
log_error("could not determine free port: "
1594
"error creating socket (%s)\n", mt_strerror(errno).c_str());
1598
server = gethostbyname("127.0.0.1");
1601
log_error("could not resolve localhost\n");
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);
1611
if (connect(fd, (struct sockaddr *)&server_addr,
1612
sizeof(server_addr)) == -1)
1620
} while (retry_count < USHRT_MAX);
1622
log_error("Could not find free port on localhost\n");