00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #include "tools.h"
00037 #include <sys/stat.h>
00038 #include <errno.h>
00039 #include <unistd.h>
00040 #include <sys/ioctl.h>
00041 #include <sys/socket.h>
00042 #include <netinet/in.h>
00043 #include <arpa/inet.h>
00044 #include <limits.h>
00045 #include <netdb.h>
00046 #include <string.h>
00047 #include "config_manager.h"
00048
00049 #ifndef SOLARIS
00050 #include <net/if.h>
00051 #else
00052 #include <fcntl.h>
00053 #include <net/if.h>
00054 #include <sys/sockio.h>
00055 #endif
00056
00057 #include "md5/md5.h"
00058 #include "file_io_handler.h"
00059 #include "metadata_handler.h"
00060
00061 #define WHITE_SPACE " \t\r\n"
00062
00063 using namespace zmm;
00064
00065 static const char *HEX_CHARS = "0123456789abcdef";
00066
00067 Ref<Array<StringBase> > split_string(String str, char sep, bool empty)
00068 {
00069 Ref<Array<StringBase> > ret(new Array<StringBase>());
00070 char *data = str.c_str();
00071 char *end = data + str.length();
00072 while (data < end)
00073 {
00074 char *pos = strchr(data, sep);
00075 if (pos == NULL)
00076 {
00077 String part = data;
00078 ret->append(part);
00079 data = end;
00080 }
00081 else if (pos == data)
00082 {
00083 data++;
00084 if ((data < end) && empty)
00085 ret->append(_(""));
00086 }
00087 else
00088 {
00089 String part(data, pos - data);
00090 ret->append(part);
00091 data = pos + 1;
00092 }
00093 }
00094 return ret;
00095 }
00096
00097 Ref<Array<StringBase> > split_path(String str)
00098 {
00099 if (! string_ok(str))
00100 throw _Exception(_("invalid path given to split_path"));
00101 Ref<Array<StringBase> > ret(new Array<StringBase>());
00102 int pos = str.rindex(DIR_SEPARATOR);
00103 const char *data = str.c_str();
00104
00105 if (pos < 0)
00106 throw _Exception(_("relative path given to split_path: ") + str);
00107
00108 if (pos == 0)
00109 {
00110
00111 ret->append(_(_DIR_SEPARATOR));
00112 String filename = data + 1;
00113 ret->append(filename);
00114 }
00115 else
00116 {
00117 String path(data, pos);
00118 ret->append(path);
00119 String filename = data + pos + 1;
00120 ret->append(filename);
00121 }
00122 return ret;
00123 }
00124
00125 String trim_string(String str)
00126 {
00127 if (str == nil)
00128 return nil;
00129 int i;
00130 int start = 0;
00131 int end = 0;
00132 int len = str.length();
00133
00134 char *buf = str.c_str();
00135
00136 for (i = 0; i < len; i++)
00137 {
00138 if (! strchr(WHITE_SPACE, buf[i]))
00139 {
00140 start = i;
00141 break;
00142 }
00143 }
00144 if (i >= len)
00145 return _("");
00146 for (i = len - 1; i >= start; i--)
00147 {
00148 if (! strchr(WHITE_SPACE, buf[i]))
00149 {
00150 end = i + 1;
00151 break;
00152 }
00153 }
00154 return str.substring(start, end - start);
00155 }
00156
00157 bool check_path(String path, bool needDir)
00158 {
00159 int ret = 0;
00160 struct stat statbuf;
00161
00162 ret = stat(path.c_str(), &statbuf);
00163 if (ret != 0) return false;
00164
00165 if ((needDir && (!S_ISDIR(statbuf.st_mode))) ||
00166 (!needDir && (S_ISDIR(statbuf.st_mode)))) return false;
00167
00168 return true;
00169 }
00170
00171 time_t check_path_ex(String path, bool needDir, bool existenceUnneeded,
00172 off_t *filesize)
00173 {
00174 int ret = 0;
00175 struct stat statbuf;
00176
00177 if (filesize != NULL)
00178 *filesize = 0;
00179
00180 ret = stat(path.c_str(), &statbuf);
00181 if (ret != 0)
00182 {
00183 if (existenceUnneeded && (errno == ENOENT))
00184 return 0;
00185
00186 throw _Exception(path + " : " + errno + (int)existenceUnneeded+ " x " + mt_strerror(errno));
00187 }
00188
00189 if (needDir && (!S_ISDIR(statbuf.st_mode)))
00190 throw _Exception(_("Not a directory: ") + path);
00191
00192 if (!needDir && (S_ISDIR(statbuf.st_mode)))
00193 throw _Exception(_("Not a file: ") + path);
00194
00195 if ((filesize != NULL) && S_ISREG(statbuf.st_mode))
00196 *filesize = statbuf.st_size;
00197
00198 return statbuf.st_mtime;
00199 }
00200
00201 bool is_executable(String path, int *err)
00202 {
00203 int ret = access(path.c_str(), R_OK | X_OK);
00204 if (err != NULL)
00205 *err = errno;
00206
00207 if (ret == 0)
00208 return true;
00209 else
00210 return false;
00211 }
00212
00213 String find_in_path(String exec)
00214 {
00215 String PATH = getenv("PATH");
00216 if (!string_ok(PATH))
00217 return nil;
00218
00219 Ref<StringTokenizer> st(new StringTokenizer(PATH));
00220 String path = nil;
00221 String next;
00222 do
00223 {
00224 if (path == nil)
00225 path = st->nextToken(_(":"));
00226 next = st->nextToken(_(":"));
00227
00228 if (path == nil)
00229 break;
00230
00231 if ((next != nil) && !next.startsWith(_("/")))
00232 {
00233 path = path + _(":") + next;
00234 next = nil;
00235 }
00236
00237 String check = path + _("/") + exec;
00238 if (check_path(check))
00239 return check;
00240
00241 if (next != nil)
00242 path = next;
00243 else
00244 path = nil;
00245
00246
00247 } while (path != nil);
00248
00249 return nil;
00250 }
00251
00252 bool string_ok(String str)
00253 {
00254 if ((str == nil) || (str == ""))
00255 return false;
00256 return true;
00257 }
00258
00259 bool string_ok(Ref<StringBuffer> str)
00260 {
00261
00262 if ((str == nil) || (str->length()<=0))
00263 return false;
00264 else
00265 return true;
00266 }
00267
00268 void string_ok_ex(String str)
00269 {
00270 if ((str == nil) || (str == ""))
00271 throw _Exception(_("Empty string"));
00272 }
00273
00274 String http_redirect_to(String ip, String port, String page)
00275 {
00276 return _("<html><head><meta http-equiv=\"Refresh\" content=\"0;URL=http://") + ip + ":" + port + "/" + page + "\"></head><body bgcolor=\"#dddddd\"></body></html>";
00277 }
00278
00279 String hex_encode(void *data, int len)
00280 {
00281 unsigned char *chars;
00282 int i;
00283 unsigned char hi, lo;
00284
00285 Ref<StringBuffer> buf(new StringBuffer(len * 2));
00286
00287 chars = (unsigned char *)data;
00288 for (i = 0; i < len; i++)
00289 {
00290 unsigned char c = chars[i];
00291 hi = c >> 4;
00292 lo = c & 0xF;
00293 *buf << HEX_CHARS[hi] << HEX_CHARS[lo];
00294 }
00295 return buf->toString();
00296
00297 }
00298
00299 String hex_decode_string(String encoded)
00300 {
00301 char *ptr = encoded.c_str();
00302 int len = encoded.length();
00303
00304 Ref<StringBuffer> buf(new StringBuffer(len / 2));
00305 for (int i = 0; i < len; i += 2)
00306 {
00307 const char *chi = strchr(HEX_CHARS, ptr[i]);
00308 const char *clo = strchr(HEX_CHARS, ptr[i + 1]);
00309 int hi, lo;
00310
00311 if (chi)
00312 hi = chi - HEX_CHARS;
00313 else
00314 hi = 0;
00315
00316 if (clo)
00317 lo = clo - HEX_CHARS;
00318 else
00319 lo = 0;
00320 char ch = (char)(hi << 4 | lo);
00321 *buf << ch;
00322 }
00323 return buf->toString();
00324 }
00325
00326 struct randomizer
00327 {
00328 struct timeval tv;
00329 int salt;
00330 };
00331 String hex_md5(void *data, int length)
00332 {
00333 char md5buf[16];
00334
00335 md5_state_t ctx;
00336 md5_init(&ctx);
00337 md5_append(&ctx, (unsigned char *)data, length);
00338 md5_finish(&ctx, (unsigned char *)md5buf);
00339
00340 return hex_encode(md5buf, 16);
00341 }
00342 String hex_string_md5(String str)
00343 {
00344 return hex_md5(str.c_str(), str.length());
00345 }
00346 String generate_random_id()
00347 {
00348 struct randomizer st;
00349 gettimeofday(&st.tv, NULL);
00350 st.salt = rand();
00351 return hex_md5(&st, sizeof(st));
00352 }
00353
00354
00355 static const char *hex = "0123456789ABCDEF";
00356
00357 String url_escape(String str)
00358 {
00359 char *data = str.c_str();
00360 int len = str.length();
00361 Ref<StringBuffer> buf(new StringBuffer(len));
00362 for (int i = 0; i < len; i++)
00363 {
00364 unsigned char c = (unsigned char)data[i];
00365 if ((c >= '0' && c <= '9') ||
00366 (c >= 'A' && c <= 'Z') ||
00367 (c >= 'a' && c <= 'z') ||
00368 c == '_' ||
00369 c == '-')
00370 {
00371 *buf << (char)c;
00372 }
00373 else
00374 {
00375 int hi = c >> 4;
00376 int lo = c & 15;
00377 *buf << '%' << hex[hi] << hex[lo];
00378 }
00379 }
00380 return buf->toString();
00381 }
00382
00383 String url_unescape(String str)
00384 {
00385 char *data = str.c_str();
00386 int len = str.length();
00387 Ref<StringBuffer> buf(new StringBuffer(len));
00388
00389 int i = 0;
00390 while (i < len)
00391 {
00392 char c = data[i++];
00393 if (c == '%')
00394 {
00395 if (i + 2 > len)
00396 break;
00397 char chi = data[i++];
00398 char clo = data[i++];
00399 int hi, lo;
00400
00401 const char *pos;
00402
00403 pos = strchr(hex, chi);
00404 if (!pos)
00405 hi = 0;
00406 else
00407 hi = pos - hex;
00408
00409 pos = strchr(hex, clo);
00410 if (!pos)
00411 lo = 0;
00412 else
00413 lo = pos - hex;
00414
00415 int ascii = (hi << 4) | lo;
00416 *buf << (char)ascii;
00417 }
00418 else if (c == '+')
00419 {
00420 *buf << ' ';
00421 }
00422 else
00423 {
00424 *buf << c;
00425 }
00426 }
00427 return buf->toString();
00428 }
00429
00430 String mime_types_to_CSV(Ref<Array<StringBase> > mimeTypes)
00431 {
00432 Ref<StringBuffer> buf(new StringBuffer());
00433 for (int i = 0; i < mimeTypes->size(); i++)
00434 {
00435 if (i > 0)
00436 *buf << ",";
00437 String mimeType = mimeTypes->get(i);
00438 *buf << "http-get:*:" << mimeType << ":*";
00439 }
00440
00441 return buf->toString();
00442 }
00443
00444 String mt_strerror(int mt_errno)
00445 {
00446 #ifdef DONT_USE_YET_HAVE_STRERROR_R
00447 char *buffer = (char *)MALLOC(512);
00448 char *err_str;
00449 #ifdef STRERROR_R_CHAR_P
00450 err_str = strerror_r(errno, buffer, 512);
00451 if (err_str == NULL)
00452 err_str = buffer;
00453 #else
00454 int ret = strerror_r(errno, buffer, 512);
00455 if (ret < 0)
00456 return _("cannot get error string: error while calling XSI-compliant strerror_r");
00457 err_str = buffer;
00458 #endif
00459 String errStr(err_str);
00460 FREE(buffer);
00461 return errStr;
00462 #else
00463 return strerror(errno);
00464 #endif
00465 }
00466
00467 String read_text_file(String path)
00468 {
00469 FILE *f = fopen(path.c_str(), "r");
00470 if (!f)
00471 {
00472 throw _Exception(_("read_text_file: could not open ") +
00473 path + " : " + mt_strerror(errno));
00474 }
00475 Ref<StringBuffer> buf(new StringBuffer());
00476 char *buffer = (char *)MALLOC(1024);
00477 size_t bytesRead;
00478 while((bytesRead = fread(buffer, 1, 1024, f)) > 0)
00479 {
00480 buf->concat(buffer, bytesRead);
00481 }
00482 fclose(f);
00483 FREE(buffer);
00484 return buf->toString();
00485 }
00486 void write_text_file(String path, String contents)
00487 {
00488 int bytesWritten;
00489 FILE *f = fopen(path.c_str(), "w");
00490 if (!f)
00491 {
00492 throw _Exception(_("write_text_file: could not open ") +
00493 path + " : " + mt_strerror(errno));
00494 }
00495
00496 bytesWritten = fwrite(contents.c_str(), 1, contents.length(), f);
00497 if (bytesWritten < contents.length())
00498 {
00499 fclose(f);
00500 if (bytesWritten >= 0)
00501 throw _Exception(_("write_text_file: incomplete write to ") +
00502 path + " : ");
00503 else
00504 throw _Exception(_("write_text_file: error writing to ") +
00505 path + " : " + mt_strerror(errno));
00506 }
00507 fclose(f);
00508 }
00509
00510 void copy_file(String from, String to)
00511 {
00512 FILE *f = fopen(from.c_str(), "r");
00513 if (!f)
00514 {
00515 throw _Exception(_("copy_file: could not open ") +
00516 from + " for read: " + mt_strerror(errno));
00517 }
00518 FILE *t = fopen(to.c_str(), "w");
00519 if (!t)
00520 {
00521 fclose(f);
00522 throw _Exception(_("copy_file: could not open ") +
00523 to + " for write: " + mt_strerror(errno));
00524 }
00525 char *buffer = (char *)MALLOC(1024);
00526 size_t bytesRead = 0;
00527 size_t bytesWritten = 0;
00528 while(bytesRead == bytesWritten && ! feof(f) && ! ferror(f) && ! ferror(t)
00529 && (bytesRead = fread(buffer, 1, 1024, f)) > 0)
00530 {
00531 bytesWritten = fwrite(buffer, 1, bytesRead, t);
00532 }
00533 FREE(buffer);
00534 if (ferror(f) || ferror(t))
00535 {
00536 int my_errno = errno;
00537 fclose(f);
00538 fclose(t);
00539 throw _Exception(_("copy_file: error while copying ") + from + " to " +
00540 to + ": " + mt_strerror(my_errno));
00541 }
00542
00543 fclose(f);
00544 fclose(t);
00545 }
00546
00547
00548 int StringBaseComparator(void *arg1, void *arg2)
00549 {
00550 return strcmp(((StringBase *)arg1)->data, ((StringBase *)arg2)->data);
00551 }
00552
00553 static void quicksort_impl(COMPARABLE *a, int lo0, int hi0, COMPARATOR comparator)
00554 {
00555 int lo = lo0;
00556 int hi = hi0;
00557
00558 if (lo >= hi)
00559 return;
00560 if( lo == hi - 1 )
00561 {
00562
00563
00564 if (comparator(a[lo], a[hi]) > 0)
00565 {
00566 COMPARABLE T = a[lo];
00567 a[lo] = a[hi];
00568 a[hi] = T;
00569 }
00570 return;
00571 }
00572
00573
00574 COMPARABLE pivot = a[(lo + hi) / 2];
00575 a[(lo + hi) / 2] = a[hi];
00576 a[hi] = pivot;
00577
00578 while( lo < hi )
00579 {
00580
00581
00582
00583 while (comparator(a[lo], pivot) <= 0 && lo < hi)
00584 {
00585 lo++;
00586 }
00587
00588
00589
00590
00591 while (comparator(pivot, a[hi]) <= 0 && lo < hi)
00592 {
00593 hi--;
00594 }
00595
00596
00597 if( lo < hi )
00598 {
00599 COMPARABLE T = a[lo];
00600 a[lo] = a[hi];
00601 a[hi] = T;
00602 }
00603 }
00604
00605
00606 a[hi0] = a[hi];
00607 a[hi] = pivot;
00608
00609
00610
00611
00612
00613
00614 quicksort_impl(a, lo0, lo-1, comparator);
00615 quicksort_impl(a, hi+1, hi0, comparator);
00616 }
00617
00618 void quicksort(COMPARABLE *arr, int size, COMPARATOR comparator)
00619 {
00620 quicksort_impl(arr, 0, size - 1, comparator);
00621 }
00622
00623 String renderProtocolInfo(String mimetype, String protocol, String extend)
00624 {
00625 if (string_ok(mimetype) && string_ok(protocol))
00626 {
00627 if (string_ok(extend))
00628 return protocol + ":*:" + mimetype + ":" + extend;
00629 else
00630 return protocol + ":*:" + mimetype + ":*";
00631 }
00632 else
00633 return _("http-get:*:*:*");
00634 }
00635
00636 String getMTFromProtocolInfo(String protocol)
00637 {
00638 Ref<Array<StringBase> > parts = split_string(protocol, ':');
00639 if (parts->size() > 2)
00640 return parts->get(2);
00641 else
00642 return nil;
00643 }
00644
00645 String getProtocol(String protocolInfo)
00646 {
00647 String protocol;
00648 int pos = protocolInfo.index(':');
00649 if (pos <= 0)
00650 protocol = _("http-get");
00651 else
00652 protocol = protocolInfo.substring(0, pos);
00653
00654 return protocol;
00655 }
00656
00657 String secondsToHMS(int seconds)
00658 {
00659 int h, m, s;
00660
00661 s = seconds % 60;
00662 seconds /= 60;
00663
00664 m = seconds % 60;
00665 h = seconds / 60;
00666
00667
00668 char *str = (char *)malloc(10);
00669 sprintf(str, "%02d:%02d:%02d", h, m, s);
00670 return String::take(str);
00671 }
00672
00673 int HMSToSeconds(String time)
00674 {
00675 if (!string_ok(time))
00676 {
00677 log_warning("Could not convert time representation to seconds!\n");
00678 return 0;
00679 }
00680
00681 int hours = 0;
00682 int minutes = 0;
00683 int seconds = 0;
00684 sscanf(time.c_str(), "%d:%d:%d", &hours, &minutes, &seconds);
00685
00686 return (hours * 3600) + (minutes * 60) + seconds;
00687 }
00688
00689 #ifdef HAVE_MAGIC
00690 String get_mime_type(magic_set *ms, Ref<RExp> reMimetype, String file)
00691 {
00692 if (ms == NULL)
00693 return nil;
00694
00695 char *mt = (char *)magic_file(ms, file.c_str());
00696 if (mt == NULL)
00697 {
00698 log_error("magic_file: %s\n", magic_error(ms));
00699 return nil;
00700 }
00701
00702 String mime_type = mt;
00703
00704 Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
00705 if (matcher->next())
00706 return matcher->group(1);
00707
00708 log_warning("filemagic returned invalid mimetype for %s\n%s\n",
00709 file.c_str(), mt);
00710 return nil;
00711 }
00712
00713 String get_mime_type_from_buffer(magic_set *ms, Ref<RExp> reMimetype,
00714 void *buffer, size_t length)
00715 {
00716 if (ms == NULL)
00717 return nil;
00718
00719 char *mt = (char *)magic_buffer(ms, buffer, length);
00720 if (mt == NULL)
00721 {
00722 log_error("magic_file: %s\n", magic_error(ms));
00723 return nil;
00724 }
00725
00726 String mime_type = mt;
00727
00728 Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
00729 if (matcher->next())
00730 return matcher->group(1);
00731
00732 log_warning("filemagic returned invalid mimetype for the given buffer%s\n",
00733 mt);
00734 return nil;
00735 }
00736 #endif
00737
00738 void set_jpeg_resolution_resource(Ref<CdsItem> item, int res_num)
00739 {
00740 try
00741 {
00742 Ref<IOHandler> fio_h(new FileIOHandler(item->getLocation()));
00743 fio_h->open(UPNP_READ);
00744 String resolution = get_jpeg_resolution(fio_h);
00745
00746 if (res_num >= item->getResourceCount())
00747 throw _Exception(_("Invalid resource index"));
00748
00749 item->getResource(res_num)->addAttribute(MetadataHandler::getResAttrName(R_RESOLUTION), resolution);
00750 }
00751 catch (Exception e)
00752 {
00753 e.printStackTrace();
00754 }
00755 }
00756
00757 bool check_resolution(String resolution, int *x, int *y)
00758 {
00759 if (x != NULL)
00760 *x = 0;
00761
00762 if (y != NULL)
00763 *y = 0;
00764
00765 Ref<Array<StringBase> > parts = split_string(resolution, 'x');
00766 if (parts->size() != 2)
00767 return false;
00768
00769 if (string_ok(parts->get(0)) &&
00770 string_ok(parts->get(1)))
00771 {
00772 int _x = _(parts->get(0)->data).toInt();
00773 int _y = _(parts->get(1)->data).toInt();
00774
00775 if ((_x > 0) && (_y > 0))
00776 {
00777 if (x != NULL)
00778 *x = _x;
00779
00780 if (y != NULL)
00781 *y = _y;
00782
00783 return true;
00784 }
00785 }
00786
00787 return false;
00788 }
00789
00790
00791 String escape(String string, char escape_char, char to_escape)
00792 {
00793 Ref<StringBase> stringBase(new StringBase(string.length() * 2));
00794 char *str = stringBase->data;
00795 int len = string.length();
00796
00797 bool possible_more_esc = true;
00798 bool possible_more_char = true;
00799
00800 int last = 0;
00801 do
00802 {
00803 int next_esc = -1;
00804 if (possible_more_esc)
00805 {
00806 next_esc = string.index(last, escape_char);
00807 if (next_esc < 0)
00808 possible_more_esc = false;
00809 }
00810
00811 int next = -1;
00812 if (possible_more_char)
00813 {
00814 next = string.index(last, to_escape);
00815 if (next < 0)
00816 possible_more_char = false;
00817 }
00818
00819 if (next < 0 || (next_esc >= 0 && next_esc < next))
00820 {
00821 next = next_esc;
00822 }
00823
00824 if (next < 0)
00825 next = len;
00826 int cpLen = next - last;
00827 if (cpLen > 0)
00828 {
00829 strncpy(str, string.charPtrAt(last), cpLen);
00830 str += cpLen;
00831 }
00832 if (next < len)
00833 {
00834 *(str++) = '\\';
00835 *(str++) = string.charAt(next);
00836 }
00837 last = next;
00838 last++;
00839 }
00840 while (last < len);
00841 *str = '\0';
00842
00843 stringBase->len = strlen(stringBase->data);
00844 return stringBase->data;
00845 }
00846
00847 String unescape(String string, char escape)
00848 {
00849 Ref<StringBase> stringBase(new StringBase(string.length()));
00850 char *str = stringBase->data;
00851 int len = string.length();
00852
00853 int last = -1;
00854 do
00855 {
00856 int next = string.index(last + 1, escape);
00857 if (next < 0)
00858 next = len;
00859 if (last < 0)
00860 last = 0;
00861 int cpLen = next - last;
00862 if (cpLen > 0)
00863 strncpy(str, string.charPtrAt(last), cpLen);
00864 str += cpLen;
00865 last = next;
00866 last++;
00867 }
00868 while (last < len);
00869 *str = '\0';
00870
00871 stringBase->len = strlen(stringBase->data);
00872 return String(stringBase);
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 String unescape_amp(String string)
00932 {
00933 if (string == nil)
00934 return nil;
00935 Ref<StringBase> stringBase(new StringBase(string.length()));
00936 char *str = stringBase->data;
00937 int len = string.length();
00938
00939 int last = 0;
00940 do
00941 {
00942 int skip = 0;
00943 int next = last - 1;
00944 do
00945 {
00946 next = string.index(next + 1, '&');
00947 if ((next < len) && (string.charAt(next + 1) == 'a') &&
00948 (string.charAt(next + 2) == 'm') &&
00949 (string.charAt(next + 3) == 'p') &&
00950 (string.charAt(next + 4) == ';'))
00951 {
00952 skip = 4;
00953 }
00954 }
00955 while(next > 0 && skip == 0);
00956
00957 if (next < 0)
00958 next = len;
00959
00960 int cpLen = next - last + 1;
00961 strncpy(str, string.charPtrAt(last), cpLen);
00962 str += cpLen;
00963 last = next + skip + 1;
00964 }
00965 while (last <= len);
00966
00967 stringBase->len = str - stringBase->data - 1;
00968 assert(stringBase->len == (int)strlen(stringBase->data));
00969 return String(stringBase);
00970 }
00971
00972 String fallbackString(String first, String fallback)
00973 {
00974 if (first==nil)
00975 return fallback;
00976 return first;
00977 }
00978
00979 unsigned int stringHash(String str)
00980 {
00981 unsigned int hash = 5381;
00982 unsigned char *data = (unsigned char *)str.c_str();
00983 int c;
00984 while ((c = *data++))
00985 hash = ((hash << 5) + hash) ^ c;
00986 return hash;
00987 }
00988
00989 String intArrayToCSV(int *array, int size)
00990 {
00991 if (size <= 0)
00992 return nil;
00993 Ref<StringBuffer> buf(new StringBuffer());
00994 for (int i = 0; i < size; i++)
00995 *buf << ',' << array[i];
00996 return buf->toString(1);
00997 }
00998
00999 void getTimespecNow(struct timespec *ts)
01000 {
01001 struct timeval tv;
01002 int ret = gettimeofday(&tv, NULL);
01003 if (ret != 0)
01004 throw _Exception(_("gettimeofday failed: ") + mt_strerror(errno));
01005
01006 ts->tv_sec = tv.tv_sec;
01007 ts->tv_nsec = tv.tv_usec * 1000;
01008 }
01009
01010 long getDeltaMillis(struct timespec *first)
01011 {
01012 struct timespec now;
01013 getTimespecNow(&now);
01014 return getDeltaMillis(first, &now);
01015 }
01016
01017 long getDeltaMillis(struct timespec *first, struct timespec *second)
01018 {
01019 return (second->tv_sec - first->tv_sec) * 1000 + (second->tv_nsec - first->tv_nsec) / 1000000;
01020 }
01021
01022 void getTimespecAfterMillis(long delta, struct timespec *ret, struct timespec *start)
01023 {
01024 struct timespec now;
01025 if (start == NULL)
01026 {
01027 getTimespecNow(&now);
01028 start = &now;
01029 }
01030 ret->tv_sec = start->tv_sec + delta / 1000;
01031 ret->tv_nsec = (start->tv_nsec + (delta % 1000) * 1000000);
01032 if (ret->tv_nsec >= 1000000000)
01033 {
01034 ret->tv_sec ++;
01035 ret->tv_nsec -= 1000000000;
01036 }
01037
01038
01039 }
01040
01041 int compareTimespecs(struct timespec *a, struct timespec *b)
01042 {
01043 if (a->tv_sec < b->tv_sec)
01044 return 1;
01045 if (a->tv_sec > b->tv_sec)
01046 return -1;
01047 if (a->tv_nsec < b->tv_nsec)
01048 return 1;
01049 if (a->tv_nsec > b->tv_nsec)
01050 return -1;
01051 return 0;
01052 }
01053
01054 String normalizePath(String path)
01055 {
01056 log_debug("Normalizing path: %s\n", path.c_str());
01057
01058 int length = path.length();
01059
01060 Ref<StringBase> result(new StringBase(length));
01061
01062 int avarageExpectedSlashes = length/5;
01063 if (avarageExpectedSlashes < 3)
01064 avarageExpectedSlashes = 3;
01065 Ref<BaseStack<int> > separatorLocations(new BaseStack<int>(avarageExpectedSlashes, -1));
01066 char *str = result->data;
01067
01068
01069 #ifndef __CYGWIN__
01070 if (path.charAt(0) != DIR_SEPARATOR)
01071 #else
01072 #error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! this function is not finished for Cygwin
01073 for (int i = 0; i < 20; i++)
01074 print_backtrace();
01076 if ((!path.length() > 1) && (path.charAt(1) != ':'))
01077 #endif
01078 throw _Exception(_("Relative paths are not allowed!\n"));
01079
01080 int next = 1;
01081 do
01082 {
01083 while (next < length && path.charAt(next) == DIR_SEPARATOR)
01084 next++;
01085 if (next >= length)
01086 break;
01087
01088 int next_sep = path.index(next, DIR_SEPARATOR);
01089 if (next_sep < 0)
01090 next_sep = length;
01091 if (next_sep == next + 1 && path.charAt(next) == '.')
01092 {
01093
01094 }
01095 else if (next_sep == next + 2 &&
01096 next + 1 < length &&
01097 path.charAt(next) == '.' &&
01098 path.charAt(next + 1) == '.')
01099 {
01100
01101
01102 int lastSepLocation = separatorLocations->pop();
01103 if (lastSepLocation < 0)
01104 lastSepLocation = 0;
01105 str = result->data + lastSepLocation;
01106 }
01107 else
01108 {
01109
01110 separatorLocations->push(str - result->data);
01111 *(str++) = DIR_SEPARATOR;
01112 int cpLen = next_sep - next;
01113 strncpy(str, path.charPtrAt(next), cpLen);
01114 str += cpLen;
01115 }
01116 next = next_sep + 1;
01117 }
01118 while(next < length);
01119
01120 if (str == result->data)
01121 *(str++) = DIR_SEPARATOR;
01122
01123 *str = 0;
01124 result->len = strlen(result->data);
01125 return String(result);
01126 }
01127
01128 String interfaceToIP(String interface)
01129 {
01130 #if defined(__CYGWIN__)
01131 struct hostent *h=NULL;
01132 struct sockaddr_in LocalAddr;
01133 char *hostname = (char *)MALLOC(256);
01134 if (!hostname)
01135 return nil;
01136
01137 gethostname(hostname, 255);
01138 hostname[255] = '\0';
01139 h=gethostbyname(hostname);
01140 free(hostname);
01141 if (h != NULL)
01142 {
01143 memcpy(&LocalAddr.sin_addr, h->h_addr_list[0],4);
01144 return String(inet_ntoa(LocalAddr.sin_addr));
01145 }
01146 return nil;
01147 #else
01148
01149 struct if_nameindex *iflist = NULL;
01150 struct if_nameindex *iflist_free = NULL;
01151 struct ifreq if_request;
01152 struct sockaddr_in local_address;
01153 int local_socket;
01154
01155 if (!string_ok(interface))
01156 return nil;
01157
01158 local_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
01159 if (local_socket < 0)
01160 {
01161 log_error("Could not create local socket: %s\n",
01162 mt_strerror(errno).c_str());
01163 return nil;
01164 }
01165
01166 iflist = iflist_free = if_nameindex();
01167 if (iflist == NULL)
01168 {
01169 log_error("Could not get interface list: %s\n",
01170 mt_strerror(errno).c_str());
01171 close(local_socket);
01172 return nil;
01173 }
01174
01175 while (iflist->if_index || iflist->if_name)
01176 {
01177 if (interface == iflist->if_name)
01178 {
01179 strncpy(if_request.ifr_name, iflist->if_name, IF_NAMESIZE);
01180 if (ioctl(local_socket, SIOCGIFADDR, &if_request) != 0)
01181 {
01182 log_error("Could not determine interface address: %s\n",
01183 mt_strerror(errno).c_str());
01184 close(local_socket);
01185 if_freenameindex(iflist_free);
01186 return nil;
01187 }
01188
01189 memcpy(&local_address, &if_request.ifr_addr, sizeof(if_request.ifr_addr));
01190 String ip = inet_ntoa(local_address.sin_addr);
01191 if_freenameindex(iflist_free);
01192 close(local_socket);
01193 return ip;
01194 }
01195 iflist++;
01196 }
01197
01198 close(local_socket);
01199 if_freenameindex(iflist_free);
01200 return nil;
01201 #endif
01202 }
01203
01204 bool validateYesNo(String value)
01205 {
01206 if ((value != "yes") && (value != "no"))
01207 return false;
01208 else
01209 return true;
01210 }
01211
01212 Ref<Array<StringBase> > parseCommandLine(String line, String in, String out)
01213 {
01214 Ref<Array<StringBase> > params = split_string(line, ' ');
01215 if ((in == nil) && (out == nil))
01216 return params;
01217
01218 for (int i = 0; i < params->size(); i++)
01219 {
01220 String param = params->get(i);
01221 String newParam = param.replace(_("%in"), in);
01222 newParam = newParam.replace(_("%out"), out);
01223 if (param != newParam)
01224 params->set(newParam, i);
01225 }
01226
01227 return params;
01228 }
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 String tempName(String leadPath, char *tmpl)
01257 {
01258 char *XXXXXX;
01259 int count;
01260 static const char letters[] =
01261 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
01262 static const int NLETTERS = sizeof (letters) - 1;
01263 long value;
01264 struct timeval tv;
01265 static int counter = 0;
01266 struct stat statbuf;
01267 int ret = 0;
01268
01269
01270 XXXXXX = strstr (tmpl, "XXXXXX");
01271
01272 if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
01273 {
01274 return nil;
01275 }
01276
01277
01278 gettimeofday(&tv, NULL);
01279 value = (tv.tv_usec ^ tv.tv_sec) + counter++;
01280
01281 for (count = 0; count < 100; value += 7777, ++count)
01282 {
01283 long v = value;
01284
01285
01286 XXXXXX[0] = letters[v % NLETTERS];
01287 v /= NLETTERS;
01288 XXXXXX[1] = letters[v % NLETTERS];
01289 v /= NLETTERS;
01290 XXXXXX[2] = letters[v % NLETTERS];
01291 v /= NLETTERS;
01292 XXXXXX[3] = letters[v % NLETTERS];
01293 v /= NLETTERS;
01294 XXXXXX[4] = letters[v % NLETTERS];
01295 v /= NLETTERS;
01296 XXXXXX[5] = letters[v % NLETTERS];
01297
01298 String check = leadPath + tmpl;
01299 ret = stat(check.c_str(), &statbuf);
01300 if (ret != 0)
01301 {
01302 if ((errno == ENOENT) ||
01303 (errno == ENOTDIR))
01304 return check;
01305 else
01306 return nil;
01307 }
01308 }
01309
01310
01311 return nil;
01312 }
01313
01314 bool isTheora(String ogg_filename)
01315 {
01316 FILE *f;
01317 char buffer[7];
01318 f = fopen(ogg_filename.c_str(), "rb");
01319
01320 if (!f)
01321 {
01322 throw _Exception(_("Error opening ") + ogg_filename + _(" : ") +
01323 mt_strerror(errno));
01324 }
01325
01326 if (fread(buffer, 1, 4, f) != 4)
01327 {
01328 fclose(f);
01329 throw _Exception(_("Error reading ") + ogg_filename);
01330 }
01331
01332 if (memcmp(buffer, "OggS", 4) != 0)
01333 {
01334 fclose(f);
01335 return false;
01336 }
01337
01338 if (fseek(f, 28, SEEK_SET) != 0)
01339 {
01340 fclose(f);
01341 throw _Exception(_("Incomplete file ") + ogg_filename);
01342 }
01343
01344 if (fread(buffer, 1, 7, f) != 7)
01345 {
01346 fclose(f);
01347 throw _Exception(_("Error reading ") + ogg_filename);
01348 }
01349
01350 if (memcmp(buffer, "\x80theora", 7) != 0)
01351 {
01352 fclose(f);
01353 return false;
01354 }
01355
01356 fclose(f);
01357 return true;
01358 }
01359
01360 String get_last_path(String location)
01361 {
01362 String path;
01363
01364 int last_slash = location.rindex(DIR_SEPARATOR);
01365 if (last_slash > 0)
01366 {
01367 path = location.substring(0, last_slash);
01368 int slash = path.rindex(DIR_SEPARATOR);
01369 if ((slash >= 0) && ((slash + 1) < path.length()))
01370 path = path.substring(slash+1);
01371 }
01372
01373 return path;
01374 }
01375
01376
01377 ssize_t getValidUTF8CutPosition(zmm::String str, size_t cutpos)
01378 {
01379 ssize_t pos = -1;
01380 size_t len = str.length();
01381
01382 if ((len == 0) || (cutpos > len))
01383 return pos;
01384
01385 printf("Character at cut position: %0x\n", (char)str.charAt(cutpos));
01386 printf("Character at cut-1 position: %0x\n", (char)str.charAt(cutpos-1));
01387 printf("Character at cut-2 position: %0x\n", (char)str.charAt(cutpos-2));
01388 printf("Character at cut-3 position: %0x\n", (char)str.charAt(cutpos-3));
01389
01390
01391 if (str.charAt(cutpos) & 0x80)
01392 {
01393
01394 if (((cutpos-1) >= 0) &&
01395 (((str.charAt(cutpos-1) & 0xc2) == 0xc2) ||
01396 ((str.charAt(cutpos-1) & 0xe2) == 0xe2) ||
01397 ((str.charAt(cutpos-1) & 0xf0) == 0xf0)))
01398 pos = cutpos - 1;
01399
01400 else if (((cutpos - 2) >= 0) &&
01401 (((str.charAt(cutpos-2) & 0xe2) == 0xe2) ||
01402 ((str.charAt(cutpos-2) & 0xf0) == 0xf0)))
01403 pos = cutpos - 2;
01404
01405 else if ((cutpos - 3) >= 0)
01406 pos = cutpos - 3;
01407 }
01408 else
01409 pos = cutpos;
01410
01411 return pos;
01412 }
01413
01414 #ifdef EXTEND_PROTOCOLINFO
01415 String getDLNAtransferHeader(String mimeType, String header)
01416 {
01417 if (ConfigManager::getInstance()->getBoolOption(CFG_SERVER_EXTEND_PROTOCOLINFO))
01418 {
01419 String transfer_parameter;
01420 if (mimeType.startsWith(_("image")))
01421 transfer_parameter = _(D_HTTP_TRANSFER_MODE_INTERACTIVE);
01422 else if (mimeType.startsWith(_("audio")) ||
01423 mimeType.startsWith(_("video")))
01424 transfer_parameter = _(D_HTTP_TRANSFER_MODE_STREAMING);
01425
01426 if (string_ok(transfer_parameter))
01427 {
01428 if (string_ok(header))
01429 header = header + _("\r\n");
01430
01431 header = header + D_HTTP_TRANSFER_MODE_HEADER +
01432 transfer_parameter;
01433 }
01434 }
01435
01436 return header;
01437 }
01438 #endif
01439
01440 #ifndef HAVE_FFMPEG
01441 String getAVIFourCC(zmm::String avi_filename)
01442 {
01443 #define FCC_OFFSET 0xbc
01444 char *buffer;
01445 FILE *f = fopen(avi_filename.c_str(), "rb");
01446 if (!f)
01447 throw _Exception(_("could not open file ") + avi_filename + " : " +
01448 mt_strerror(errno));
01449
01450 buffer = (char *)MALLOC(FCC_OFFSET+6);
01451 if (buffer == NULL)
01452 {
01453 fclose(f);
01454 throw _Exception(_("Out of memory when allocating buffer for file ") +
01455 avi_filename);
01456 }
01457
01458 size_t rb = fread(buffer, 1, FCC_OFFSET+4, f);
01459 fclose(f);
01460 if (rb != FCC_OFFSET+4)
01461 {
01462 free(buffer);
01463 throw _Exception(_("could not read header of ") + avi_filename +
01464 " : " + mt_strerror(errno));
01465 }
01466
01467 buffer[FCC_OFFSET+5] = '\0';
01468
01469 if (strncmp(buffer, "RIFF", 4) != 0)
01470 {
01471 free(buffer);
01472 return nil;
01473 }
01474
01475 if (strncmp(buffer+8, "AVI ", 4) != 0)
01476 {
01477 free(buffer);
01478 return nil;
01479 }
01480
01481 String fourcc = String(buffer+FCC_OFFSET, 4);
01482 free(buffer);
01483
01484 if (string_ok(fourcc))
01485 return fourcc;
01486 else
01487 return nil;
01488 }
01489 #endif
01490
01491 #ifdef TOMBDEBUG
01492
01493 void profiling_thread_check(struct profiling_t *data)
01494 {
01495 if (data->thread != pthread_self())
01496 {
01497 log_debug("profiling_..() called from a different thread than profiling_init was called! (init: %d; this: %d) - aborting...\n", data->thread, pthread_self());
01498 print_backtrace();
01499 abort();
01500 return;
01501 }
01502 }
01503
01504
01505 void profiling_start(struct profiling_t *data)
01506 {
01507 profiling_thread_check(data);
01508 if (data->running)
01509 {
01510 log_debug("profiling_start() called on an already running profile! - aborting...\n");
01511 print_backtrace();
01512 abort();
01513 return;
01514 }
01515 data->running = true;
01516 getTimespecNow(&(data->last_start));
01517 }
01518
01519 void profiling_end(struct profiling_t *data)
01520 {
01521 profiling_thread_check(data);
01522 struct timespec now;
01523 getTimespecNow(&now);
01524 if (! data->running)
01525 {
01526 log_debug("profiling_end() called on a not-running profile! - aborting...\n");
01527 print_backtrace();
01528 abort();
01529 return;
01530 }
01531 struct timespec *sum = &(data->sum);
01532 struct timespec *last_start = &(data->last_start);
01533 sum->tv_sec += now.tv_sec - last_start->tv_sec;
01534
01535 if (now.tv_nsec >= last_start->tv_nsec)
01536 {
01537 sum->tv_nsec += now.tv_nsec - last_start->tv_nsec;
01538
01539 }
01540 else
01541 {
01542 sum->tv_nsec += 1000000000L - last_start->tv_nsec + now.tv_nsec;
01543 sum->tv_sec --;
01544 }
01545 if(sum->tv_nsec >= 1000000000L)
01546 {
01547 sum->tv_nsec -= 1000000000L;
01548 sum->tv_sec ++;
01549 }
01550
01551 data->running = false;
01552 }
01553
01554 void profiling_print(struct profiling_t *data)
01555 {
01556 if (data->running)
01557 {
01558 log_debug("profiling_print() called on running profile! - aborting...\n");
01559 print_backtrace();
01560 abort();
01561 return;
01562 }
01563
01564 log_debug("PROFILING: took %ld sec %ld nsec\n", data->sum.tv_sec, data->sum.tv_nsec);
01565 }
01566
01567 #endif
01568
01569 #ifdef SOPCAST
01571 int find_local_port(unsigned short range_min, unsigned short range_max)
01572 {
01573 int fd;
01574 int retry_count = 0;
01575 int port;
01576 struct sockaddr_in server_addr;
01577 struct hostent *server;
01578
01579 if (range_min > range_max)
01580 {
01581 log_error("min port range > max port range!\n");
01582 return -1;
01583 }
01584
01585
01586 do
01587 {
01588 port = rand () % (range_max - range_min) + range_min;
01589
01590 fd = socket(AF_INET, SOCK_STREAM, 0);
01591 if (fd < 0)
01592 {
01593 log_error("could not determine free port: "
01594 "error creating socket (%s)\n", mt_strerror(errno).c_str());
01595 return -1;
01596 }
01597
01598 server = gethostbyname("127.0.0.1");
01599 if (server == NULL)
01600 {
01601 log_error("could not resolve localhost\n");
01602 close(fd);
01603 return -1;
01604 }
01605
01606 memset(&server_addr, 0, sizeof(server_addr));
01607 server_addr.sin_family = AF_INET;
01608 memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);
01609 server_addr.sin_port = htons(port);
01610
01611 if (connect(fd, (struct sockaddr *)&server_addr,
01612 sizeof(server_addr)) == -1)
01613 {
01614 close(fd);
01615 return port;
01616 }
01617
01618 retry_count++;
01619
01620 } while (retry_count < USHRT_MAX);
01621
01622 log_error("Could not find free port on localhost\n");
01623
01624 return -1;
01625 }
01626 #endif