diff --git a/src/conf.c b/src/conf.c index 73434e1a..359c457a 100644 --- a/src/conf.c +++ b/src/conf.c @@ -201,7 +201,7 @@ int _conf_existdir(char *path) { DPRINTF(E_DBG,L_CONF,"Checking existence of %s\n",path); - if(stat(path,&sb)) { + if(os_stat(path,&sb)) { return FALSE; } diff --git a/src/configfile.c b/src/configfile.c index 9e41a30f..7d251c68 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -339,7 +339,7 @@ void config_handler(WS_CONNINFO *pwsc) { } /* this is quite broken, but will work */ - stat(resolved_path,&sb); + os_stat(resolved_path,&sb); if(sb.st_mode & S_IFDIR) { ws_addresponseheader(pwsc,"Location","/index.html"); ws_returnerror(pwsc,302,"Moved"); @@ -806,7 +806,7 @@ void config_emit_include(WS_CONNINFO *pwsc, void *value, char *arg) { } /* this should really return a 302:Found */ - stat(resolved_path,&sb); + os_stat(resolved_path,&sb); if(sb.st_mode & S_IFDIR) { ws_writefd(pwsc,"
error: cannot include dir %s
",arg); return; diff --git a/src/err.c b/src/err.c index 96788f14..a6bd0144 100644 --- a/src/err.c +++ b/src/err.c @@ -106,7 +106,7 @@ void err_reopen(void) { if(!(err_logdest & LOGDEST_LOGFILE)) return; - _err_lock(); +// _err_lock(); fclose(err_file); err_file = fopen(err_filename,"a"); if(!err_file) { @@ -122,7 +122,7 @@ void err_reopen(void) { strerror(err)); return; } - _err_unlock(); +// _err_unlock(); DPRINTF(E_LOG,L_MISC,"Rotated logs\n"); } @@ -257,7 +257,7 @@ int err_setlogfile(char *file) { if(strcmp(file,err_filename) == 0) return TRUE; */ - _err_lock(); +// _err_lock(); if(err_file) { fclose(err_file); @@ -279,7 +279,7 @@ int err_setlogfile(char *file) { result=FALSE; } - _err_unlock(); +// _err_unlock(); return result; } diff --git a/src/mp3-scanner.c b/src/mp3-scanner.c index 3a5192c8..f86946fb 100644 --- a/src/mp3-scanner.c +++ b/src/mp3-scanner.c @@ -364,7 +364,7 @@ int scan_path(char *path) { mp3_path[0] = '\x0'; realpath(relative_path,mp3_path); DPRINTF(E_DBG,L_SCAN,"Found %s\n",relative_path); - if(stat(mp3_path,&sb)) { + if(os_stat(mp3_path,&sb)) { DPRINTF(E_WARN,L_SCAN,"Error statting: %s\n",strerror(errno)); } else { if(sb.st_mode & S_IFDIR) { /* dir -- recurse */ @@ -411,7 +411,7 @@ int scan_static_playlist(char *path) { char *ptr; DPRINTF(E_WARN,L_SCAN|L_PL,"Processing static playlist: %s\n",path); - if(stat(path,&sb)) { + if(os_stat(path,&sb)) { DPRINTF(E_WARN,L_SCAN,"Error statting %s: %s\n",path,strerror(errno)); return FALSE; } @@ -567,7 +567,7 @@ void scan_filename(char *path, int compdir, char *extensions) { } - if(stat(mp3_path,&sb)) { + if(os_stat(mp3_path,&sb)) { DPRINTF(E_WARN,L_SCAN,"Error statting: %s\n",strerror(errno)); } else { /* we assume this is regular file */ diff --git a/src/os-win32-u.c b/src/os-win32-u.c new file mode 100644 index 00000000..a40b6bf0 --- /dev/null +++ b/src/os-win32-u.c @@ -0,0 +1,153 @@ +/* + * Win32 os functions that require unicode + */ + +#define _UNICODE +#define UNICODE + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include + +#include "daapd.h" +#include "win32.h" +#include "err.h" +#include "os-win32.h" +#include "util.h" + +/* opendir/closedir/readdir emulation taken from emacs. Thanks. :) */ +DIR *os_opendir(char *filename) { + DIR *dirp; + + /* Opening is done by FindFirstFile. However, a read is inherent to + this operation, so we defer the open until read time. */ + + if (!(dirp = (DIR *) malloc (sizeof (DIR)))) + return NULL; + + dirp->dir_find_handle = INVALID_HANDLE_VALUE; + dirp->dd_fd = 0; + dirp->dd_loc = 0; + dirp->dd_size = 0; + + strncpy (dirp->dir_pathname, filename,PATH_MAX); + dirp->dir_pathname[PATH_MAX] = '\0'; + + return dirp; +} + +void os_closedir(DIR *dirp) { + /* If we have a find-handle open, close it. */ + if (dirp->dir_find_handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->dir_find_handle); + } + free((char *) dirp); +} + + +int os_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { + char filename[PATH_MAX + 1]; + WCHAR utf16[PATH_MAX + 1]; + int ln; + + if (dirp->dir_find_handle == INVALID_HANDLE_VALUE) { + /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ + strncpy (filename, dirp->dir_pathname,PATH_MAX - 3); + ln = (int) strlen (filename) - 1; + if(filename[ln] != '\\') + strcat (filename, "\\"); + strcat (filename, "*"); + + /* filename is utf-8... let's convert to unicode */ + util_utf8toutf16((unsigned char *)&utf16,sizeof(utf16),filename,(int)strlen(filename)); + + dirp->dir_find_handle = FindFirstFile(utf16, &dirp->dir_find_data); + + if (dirp->dir_find_handle == INVALID_HANDLE_VALUE) { + *result=NULL; + return 2; + } + } else { + if (!FindNextFile (dirp->dir_find_handle, &dirp->dir_find_data)) { + *result = NULL; + return 0; + } + } + + /* Emacs never uses this value, so don't bother making it match + value returned by stat(). */ + entry->d_ino = 1; + + memset(entry->d_name,0,MAXNAMLEN+1); + util_utf16toutf8(entry->d_name,MAXNAMLEN+1, + (unsigned char *)&dirp->dir_find_data.cFileName, + (int)wcslen(dirp->dir_find_data.cFileName)*2); + entry->d_namlen = (int) strlen (entry->d_name); + + entry->d_reclen = sizeof (struct dirent) - MAXNAMLEN + 3 + + entry->d_namlen - entry->d_namlen % 4; + + entry->d_type = 0; + if(dirp->dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + entry->d_type |= DT_DIR; + } else if(dirp->dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) { + entry->d_type |= DT_REG; + } + + /* + if (dir_is_fat) + _strlwr (dir_static.d_name); + else if (!NILP (Vw32_downcase_file_names)) { + register char *p; + for (p = dir_static.d_name; *p; p++) + if (*p >= 'a' && *p <= 'z') + break; + if (!*p) + _strlwr (dir_static.d_name); + } + */ + *result = entry; + return 0; +} + +int os_stat(const char *path, struct _stat *sb) { + WCHAR utf16_path[PATH_MAX+1]; + + memset(utf16_path,0,sizeof(utf16_path)); + util_utf8toutf16((unsigned char *)&utf16_path,PATH_MAX * 2,(char*)path,(int)strlen(path)); + + return _wstat(utf16_path,sb); +} + +/* FIXME: mode */ +int os_open(const char *filename, int oflag) { + WCHAR utf16_path[PATH_MAX+1]; + int fd; + + memset(utf16_path,0,sizeof(utf16_path)); + util_utf8toutf16((unsigned char *)&utf16_path,PATH_MAX * 2,(char*)filename,(int)strlen(filename)); + + fd = _wopen(utf16_path, oflag | O_BINARY); + return fd; +} + +FILE *os_fopen(const char *filename, const char *mode) { + WCHAR utf16_path[PATH_MAX+1]; + WCHAR utf16_mode[10]; + + memset(utf16_path,0,sizeof(utf16_path)); + memset(utf16_mode,0,sizeof(utf16_mode)); + util_utf8toutf16((unsigned char *)&utf16_path,PATH_MAX * 2,(char*)filename,(int)strlen(filename)); + util_utf8toutf16((unsigned char *)&utf16_mode,10 * 2,(char*)mode,(int)strlen(mode)); + return _wfopen((wchar_t *)&utf16_path, (wchar_t *)&utf16_mode); +} + + diff --git a/src/os-win32.c b/src/os-win32.c index f1c2d375..1983c3ae 100644 --- a/src/os-win32.c +++ b/src/os-win32.c @@ -1,7 +1,6 @@ /* $Id$ * */ - #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -19,6 +18,7 @@ #include "plugin.h" #include "w32-eventlog.h" #include "w32-service.h" +#include "util.h" /* Globals */ static WSADATA w32_wsadata; @@ -425,13 +425,6 @@ int os_shutdown(int fd, int how) { return 0; } -/* FIXME: mode */ -int os_open(const char *filename, int oflag) { - int fd; - - fd = _open(filename, oflag | O_BINARY); - return fd; -} int os_close(int fd) { if(NOTSOCK) { @@ -470,7 +463,7 @@ char *os_realpath(const char *pathname, char *resolved_path) { ptr = resolved_path; while(*ptr) { - *ptr = tolower(*ptr); +// *ptr = tolower(*ptr); if(*ptr == '/') *ptr = '\\'; ptr++; @@ -524,92 +517,6 @@ void _os_socket_shutdown(void) { /* COMPAT FUNCTIONS */ -/* opendir/closedir/readdir emulation taken from emacs. Thanks. :) */ -DIR *os_opendir(char *filename) { - DIR *dirp; - - /* Opening is done by FindFirstFile. However, a read is inherent to - this operation, so we defer the open until read time. */ - - if (!(dirp = (DIR *) malloc (sizeof (DIR)))) - return NULL; - - dirp->dir_find_handle = INVALID_HANDLE_VALUE; - dirp->dd_fd = 0; - dirp->dd_loc = 0; - dirp->dd_size = 0; - - strncpy (dirp->dir_pathname, filename,_MAX_PATH); - dirp->dir_pathname[_MAX_PATH] = '\0'; - - return dirp; -} - -void os_closedir(DIR *dirp) { - /* If we have a find-handle open, close it. */ - if (dirp->dir_find_handle != INVALID_HANDLE_VALUE) { - FindClose(dirp->dir_find_handle); - } - free((char *) dirp); -} - - -int os_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { - if (dirp->dir_find_handle == INVALID_HANDLE_VALUE) { - /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ - char filename[MAXNAMLEN + 3]; - int ln; - - strcpy (filename, dirp->dir_pathname); - ln = (int) strlen (filename) - 1; - if(filename[ln] != '\\') - strcat (filename, "\\"); - strcat (filename, "*"); - - dirp->dir_find_handle = FindFirstFile (filename, &dirp->dir_find_data); - - if (dirp->dir_find_handle == INVALID_HANDLE_VALUE) { - *result=NULL; - return 2; - } - } else { - if (!FindNextFile (dirp->dir_find_handle, &dirp->dir_find_data)) { - *result = NULL; - return 0; - } - } - - /* Emacs never uses this value, so don't bother making it match - value returned by stat(). */ - entry->d_ino = 1; - - entry->d_namlen = (int) strlen (dirp->dir_find_data.cFileName); - entry->d_reclen = sizeof (struct dirent) - MAXNAMLEN + 3 + - entry->d_namlen - entry->d_namlen % 4; - strcpy (entry->d_name, dirp->dir_find_data.cFileName); - - entry->d_type = 0; - if(dirp->dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - entry->d_type |= DT_DIR; - } else if(dirp->dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) { - entry->d_type |= DT_REG; - } - - /* - if (dir_is_fat) - _strlwr (dir_static.d_name); - else if (!NILP (Vw32_downcase_file_names)) { - register char *p; - for (p = dir_static.d_name; *p; p++) - if (*p >= 'a' && *p <= 'z') - break; - if (!*p) - _strlwr (dir_static.d_name); - } - */ - *result = entry; - return 0; -} /* can't be worse then strerror */ char *os_strerror (int error_no) { diff --git a/src/os-win32.h b/src/os-win32.h index 32f9ff12..d2942dd8 100644 --- a/src/os-win32.h +++ b/src/os-win32.h @@ -42,7 +42,7 @@ typedef struct { int dd_size; /* amount of valid data */ char dd_buf[DIRBLKSIZ]; /* directory block */ HANDLE dir_find_handle; - char dir_pathname[_MAX_PATH+1]; + char dir_pathname[PATH_MAX+1]; WIN32_FIND_DATA dir_find_data; } DIR; @@ -58,6 +58,8 @@ extern int os_shutdown(int fd, int how); extern int os_waitfdtimed(int fd, struct timeval end); extern int os_close(int fd); extern int os_open(const char *filename, int oflag); +extern FILE *os_fopen(const char *filename, const char *mode); + extern int os_read(int fd,void *buffer,unsigned int count); extern int os_write(int fd, void *buffer, unsigned int count); extern int os_getuid(void); diff --git a/src/os.h b/src/os.h index 86e3a7a3..498b4df3 100644 --- a/src/os.h +++ b/src/os.h @@ -39,6 +39,7 @@ extern void *os_libfunc(char **pe, void *handle, char *function); extern int os_unload(void *handle); /* misc */ +extern int os_stat(const char *path, struct stat *sb); extern int os_islocaladdr(char *hostaddr); extern char *os_apppath(char *parm); diff --git a/src/plugins/ssc-ffmpeg.c b/src/plugins/ssc-ffmpeg.c index 68ad2f10..760cad32 100644 --- a/src/plugins/ssc-ffmpeg.c +++ b/src/plugins/ssc-ffmpeg.c @@ -6,6 +6,8 @@ # include "config.h" #endif +#undef fopen + #include #include #include diff --git a/src/scan-mp3.c b/src/scan-mp3.c index afbd78cd..4cd7cb16 100644 --- a/src/scan-mp3.c +++ b/src/scan-mp3.c @@ -291,6 +291,7 @@ int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) { int err; int index; int used; + int mp3_fd; char *utf8_text; int genre=WINAMP_GENRE_UNKNOWN; int have_utf8; @@ -300,7 +301,13 @@ int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) { int got_numeric_genre; int rating; - pid3file=id3_file_open(file,ID3_FILE_MODE_READONLY); + mp3_fd = open(file,O_RDONLY); + if(mp3_fd == -1) { + DPRINTF(E_WARN,L_SCAN,"Cannot open %s\n",file); + return FALSE; + } + + pid3file=id3_file_fdopen(mp3_fd,ID3_FILE_MODE_READONLY); if(!pid3file) { DPRINTF(E_WARN,L_SCAN,"Cannot open %s\n",file); return FALSE; diff --git a/src/scan-wma.c b/src/scan-wma.c index aa1f0d7b..b9c053e9 100644 --- a/src/scan-wma.c +++ b/src/scan-wma.c @@ -427,7 +427,6 @@ int wma_parse_extended_content_description(int fd,int size, MP3FILE *pmp3) { int fail=0; int track, tracknumber; char numbuff[40]; - int new_size; char *tmp; @@ -528,8 +527,8 @@ int wma_parse_extended_content_description(int fd,int size, MP3FILE *pmp3) { pmp3->composer = descriptor_byte_value; descriptor_byte_value = NULL; } else { - size = strlen(pmp3->composer) + 1 + - strlen(descriptor_byte_value) + 1; + size = (int)strlen(pmp3->composer) + 1 + + (int)strlen(descriptor_byte_value) + 1; tmp = malloc(size); if(!tmp) DPRINTF(E_FATAL,L_SCAN,"malloc: wma_ext_content_descr\n"); diff --git a/src/scan-xml.c b/src/scan-xml.c index a22d0f85..14048856 100644 --- a/src/scan-xml.c +++ b/src/scan-xml.c @@ -159,7 +159,7 @@ int scan_xml_rb_compare(const void *pa, const void *pb, const void *cfg) { int scan_xml_is_file(char *path) { struct stat sb; - if(stat(path,&sb)) + if(os_stat(path,&sb)) return 0; if(sb.st_mode & S_IFREG) diff --git a/src/util.c b/src/util.c index 68655210..426c147b 100644 --- a/src/util.c +++ b/src/util.c @@ -14,8 +14,20 @@ #include #include -#include "daapd.h" +//#include +#include "daapd.h" +#include "err.h" +#include "util.h" + +/* Forwards */ +//int _util_xtoy(unsigned char *dbuffer, size_t dlen, unsigned char *sbuffer, size_t slen, char *from, char *to); +void _util_hexdump(unsigned char *block, int len); + + +/** + * Simple hash generator + */ uint32_t util_djb_hash_block(unsigned char *data, uint32_t len) { uint32_t hash = 5381; unsigned char *pstr = data; @@ -27,7 +39,9 @@ uint32_t util_djb_hash_block(unsigned char *data, uint32_t len) { return hash; } - +/** + * simple hash generator + */ uint32_t util_djb_hash_str(char *str) { uint32_t len; @@ -35,6 +49,362 @@ uint32_t util_djb_hash_str(char *str) { return util_djb_hash_block((unsigned char *)str,len); } +/** + * Dumb utility function that should probably be somehwere else + */ int util_must_exit(void) { return config.stop; } + +/** + * calculate how long a utf16le string will be once converted + */ +int util_utf16toutf8_len(unsigned char *utf16, int len) { + char *src = utf16; + int out_len = 0; + uint16_t temp_word; + + while(src+2 <= utf16 + len) { + temp_word = src[1] << 8 | src[0]; + + if((temp_word & 0xFC00) == 0xD800) { + src += 2; + if(src + 2 <= utf16 + len) { + out_len += 4; + } else { + return -1; + } + } else { + if(temp_word <= 0x7F) + out_len += 1; + else if(temp_word <= 0x7FF) + out_len += 2; + else if(temp_word <= 0xFFFF) + out_len += 3; + } + + src += 2; + } + return out_len; +} + +/** + * convert utf16 string to utf8. This is a bit naive, but... + * Since utf-8 can't expand past 4 bytes per code point, and + * we're converting utf-16, we can't be more than 2n+1 bytes, so + * we'll just allocate that much. + * + * Probably it could be more efficiently calculated, but this will + * always work. Besides, these are small strings, and will be freed + * after the db insert. + * + * We assume this is utf-16LE, as it comes from windows + * + * @param utf16 utf-16 to convert + * @param len length of utf-16 string + */ + +int util_utf16toutf8(unsigned char *utf8, int dlen, unsigned char *utf16, int len) { + unsigned char *src=utf16; + char *dst; + unsigned int w1, w2; + int bytes; + int new_len; + + if(!len) + return FALSE; + + new_len = util_utf16toutf8_len(utf16,len); + if((new_len == -1) || (dlen <= new_len)) { + DPRINTF(E_LOG,L_MISC,"Cannot convert %s to utf8; E2BIG (%d vs %d)\n",utf8,new_len,dlen); + return FALSE; + } + + dst=utf8; + while((src+2) <= utf16+len) { + w1=src[1] << 8 | src[0]; + src += 2; + if((w1 & 0xFC00) == 0xD800) { // could be surrogate pair + if(src+2 > utf16+len) { + DPRINTF(E_INF,L_SCAN,"Invalid utf-16 in file\n"); + return FALSE; + } + w2 = src[3] << 8 | src[2]; + if((w2 & 0xFC00) != 0xDC00) { + DPRINTF(E_INF,L_SCAN,"Invalid utf-16 in file\n"); + return FALSE; + } + + // get bottom 10 of each + w1 = w1 & 0x03FF; + w1 = w1 << 10; + w1 = w1 | (w2 & 0x03FF); + + // add back the 0x10000 + w1 += 0x10000; + } + + // now encode the original code point in utf-8 + if (w1 < 0x80) { + *dst++ = w1; + bytes=0; + } else if (w1 < 0x800) { + *dst++ = 0xC0 | (w1 >> 6); + bytes=1; + } else if (w1 < 0x10000) { + *dst++ = 0xE0 | (w1 >> 12); + bytes=2; + } else { + *dst++ = 0xF0 | (w1 >> 18); + bytes=3; + } + + while(bytes) { + *dst++ = 0x80 | ((w1 >> (6*(bytes-1))) & 0x3f); + bytes--; + } + } + + *dst = '\x0'; + + return TRUE; +} + +/** + * calculate how long a utf8 string will be once converted + */ +int util_utf8toutf16_len(unsigned char *utf8) { + int len,out_len,trailing_bytes; + unsigned char *src = utf8; + + len=(int)strlen(utf8); + out_len = 0; + + while(src < utf8 + len) { + trailing_bytes = 0; + if((*src & 0xE0) == 0xC0) trailing_bytes = 1; + else if((*src & 0xF0) == 0xE0) trailing_bytes = 2; + else if((*src & 0xF8) == 0xF0) trailing_bytes = 3; + + if(src + trailing_bytes > utf8 + len) + return -1; + + out_len += 2; + if(trailing_bytes == 3) /* surrogate pair */ + out_len += 2; + + src += (1 + trailing_bytes); + } + + return out_len; +} + +unsigned char *util_utf8toutf16_alloc(unsigned char *utf8) { + unsigned char *out; + int new_len; + + new_len = util_utf8toutf16_len(utf8); + if(new_len == -1) + return NULL; + + out = calloc(1,new_len + 2); + if(!util_utf8toutf16(out,new_len + 2,utf8,(int)strlen(utf8))) { + free(out); + return NULL; + } + + return out; +} + +unsigned char *util_utf16touft8_alloc(unsigned char *utf16, int len) { + unsigned char *out; + int new_len; + + new_len = util_utf16toutf8_len(utf16,len); + if(new_len == -1) + return NULL; + + out = calloc(1,new_len + 1); + if(!util_utf16toutf8(out,new_len + 1,utf16,len)) { + free(out); + return NULL; + } + return out; +} + + int util_utf8toutf16(unsigned char *utf16, int dlen, unsigned char *utf8, int len) { + unsigned char *src=utf8; + char *dst; + int new_len; + int trailing_bytes; + uint32_t utf32; + uint16_t temp_word; + + len=(int)strlen(utf8); /* ignore passed length, might be wrong! */ + if(!len) + return FALSE; + + new_len = util_utf8toutf16_len(utf8); + if((new_len == -1) || (dlen <= (new_len+1))) { + DPRINTF(E_LOG,L_MISC,"Cannot convert %s to utf16; E2BIG (%d vs %d)\n",utf8,new_len,dlen); + return FALSE; + } + + dst=utf16; + + while(src < utf8 + len) { + utf32=0; + trailing_bytes=0; + + if((*src & 0xE0) == 0xC0) trailing_bytes = 1; + else if((*src & 0xF0) == 0xE0) trailing_bytes = 2; + else if((*src & 0xF8) == 0xF0) trailing_bytes = 3; + + if(src + trailing_bytes > utf8 + len) { + DPRINTF(E_LOG,L_SCAN,"Invalid UTF8 string\n"); + return FALSE; + } + + switch(trailing_bytes) { + case 0: + utf32 = *src; + break; + case 1: + utf32 = ((src[0] & 0x1F) << 6) | + (src[1] & 0x3F); + break; + case 2: + utf32 = ((src[0] & 0x0F) << 12) | + ((src[1] & 0x3F) << 6) | + ((src[2] & 0x3F)); + break; + case 3: + utf32 = ((src[0] & 0x07) << 18) | + ((src[1] & 0x3F) << 12) | + ((src[2] & 0x3F) << 6) | + ((src[3] & 0x3F)); + break; + } + + if(utf32 <= 0xFFFF) { + /* we are encoding LE style... */ + *dst++ = utf32 & 0xFF; + *dst++ = (utf32 & 0xFF00) >> 8; + } else { + /* Encode with surrogates */ + temp_word = 0xD800 | ((utf32 & 0x0FFC00) >> 10); + *dst++ = temp_word & 0xFF; + *dst++ = (temp_word & 0xFF00) >> 8; + temp_word = 0xDC00 | (utf32 & 0x3FF); + *dst++ = temp_word & 0xFF; + *dst++ = (temp_word & 0xFF00) >> 8; + } + + src += (trailing_bytes + 1); + } + + *dst++ = '\x0'; + *dst = '\x0'; + return TRUE; +} + +/* +int util_utf8toutf16(unsigned char *utf16, size_t dlen, unsigned char *utf8, size_t slen) { + int result; + DPRINTF(E_DBG,L_MISC,"Converting %s to utf-16le (slen=%d, dlen=%d)\n",utf8,slen,dlen); + + result=_util_xtoy(utf16, dlen, utf8, slen, "UTF-8","UTF-16LE"); + DPRINTF(E_DBG,L_MISC,"Result: %d\n",result); + _util_hexdump(utf16,32); + return result; +} + +int util_utf16toutf8(unsigned char *utf8, size_t dlen, unsigned char *utf16, size_t slen) { + int result; + + DPRINTF(E_DBG,L_MISC,"Converting *something* to utf-8 (slen=%d, dlen=%d)\n",slen,dlen); + _util_hexdump(utf16,32); + result = _util_xtoy(utf8, dlen, utf16, slen, "UTF-16LE","UTF-8"); + + DPRINTF(E_DBG,L_MISC,"Converted to %s\n",utf8); + + return result; +} + +unsigned char *util_alloc_utf16toutf8(unsigned char *utf16, size_t slen) { + char *utf8; + + utf8=calloc(1, slen * 2 + 1); + if(_util_xtoy(utf8,slen * 2 + 1,utf16,slen,"UTF-16LE","UTF-8")) { + return utf8; + } + + free(utf8); + return NULL; +} + +int _util_xtoy(unsigned char *dbuffer, size_t dlen, unsigned char *sbuffer, size_t slen, char *from, char *to) { + iconv_t iv; + size_t csize; + + iv=iconv_open(to,from); + if(iv == (iconv_t)-1) { + DPRINTF(E_LOG,L_MISC,"iconv error: iconv_open failed with %d\n",errno); + } + + csize = iconv(iv,&sbuffer,&slen,&dbuffer,&dlen); + if(csize == (size_t)-1) { + switch(errno) { + case EILSEQ: + DPRINTF(E_LOG,L_MISC,"iconv error: Invalid multibyte sequence\n"); + break; + case EINVAL: + DPRINTF(E_LOG,L_MISC,"iconv error: Incomplete multibyte sequence\n"); + break; + case E2BIG: + DPRINTF(E_LOG,L_MISC,"iconv error: Insufficient buffer size\n"); + break; + default: + DPRINTF(E_LOG,L_MISC,"iconv error: unknown (%d)\n",errno); + break; + } + } + iconv_close(iv); + + return (csize != (size_t)-1); +} +*/ + +void _util_hexdump(unsigned char *block, int len) { + char charmap[256]; + int index; + int row, offset; + char output[80]; + char tmp[20]; + + memset(charmap,'.',sizeof(charmap)); + + for(index=' ';index<'~';index++) charmap[index]=index; + for(row=0;row<(len+15)/16;row++) { + sprintf(output,"%04X: ",row*16); + for(offset=0; offset < 16; offset++) { + if(row * 16 + offset < len) { + sprintf(tmp,"%02X ",block[row*16 + offset]); + } else { + sprintf(tmp," "); + } + strcat(output,tmp); + } + + for(offset=0; offset < 16; offset++) { + if(row * 16 + offset < len) { + sprintf(tmp,"%c",charmap[block[row*16 + offset]]); + } else { + sprintf(tmp," "); + } + strcat(output,tmp); + } + + fprintf(stderr,"%s\n",output); + } +} diff --git a/src/util.h b/src/util.h index a7e721e3..2b0306ab 100644 --- a/src/util.h +++ b/src/util.h @@ -21,5 +21,19 @@ extern uint32_t util_djb_hash_str(char *str); extern int util_must_exit(void); +//extern char *util_utf16toutf8(unsigned char *utf16, int len); +//int util_utf8toutf16(unsigned char *utf16, size_t dlen, unsigned char *utf8, size_t slen); +//int util_utf16toutf8(unsigned char *utf8, size_t dlen, unsigned char *utf16, size_t slen); +//unsigned char *util_alloc_utf16toutf8(unsigned char *utf16, int slen); + +extern unsigned char *util_utf8toutf16_alloc(unsigned char *utf8); +extern unsigned char *util_utf16touft8_alloc(unsigned char *utf16, int len); +extern int util_utf8toutf16_len(unsigned char *utf8); +extern int util_utf16toutf8_len(unsigned char *utf16, int len); +extern int util_utf8toutf16(unsigned char *utf16, int dlen, unsigned char *utf8, int len); +extern int util_utf16toutf8(unsigned char *utf8, int dlen, unsigned char *utf16, int len); + + + #endif /* _UTIL_H_ */ diff --git a/src/win32.h b/src/win32.h index 64c0c4f3..0d886d0f 100644 --- a/src/win32.h +++ b/src/win32.h @@ -25,6 +25,23 @@ #include #include +/* Type fixups */ +#define mode_t int +#define ssize_t int +#define socklen_t int + +/* Consts */ +#define PIPE_BUF 256 /* What *should* this be on win32? */ +#define MAXDESC 512 /* http://msdn.microsoft.com/en-us/library/kdfaxaay.aspx */ +#define SHUT_RDWR 2 +#define ETIME 101 +#define PATH_MAX 512 /* it's clearly not _MAX_PATH... other projects seem to use 512 */ +#define MAX_NAME_LEN _MAX_PATH +#define EADDRINUSE WSAEADDRINUSE + +#define HOST "unknown-windows-ick" +#define SERVICENAME "Firefly Media Server" + #include "os-win32.h" #ifndef TRUE @@ -65,6 +82,7 @@ typedef INT32 int32_t; #define strsep os_strsep #define open os_open #define waitfdtimed os_waitfdtimed +#define fopen os_fopen #define readdir_r os_readdir_r #define closedir os_closedir @@ -80,22 +98,6 @@ typedef INT32 int32_t; /* privately implemented functions: @see os-win32.c */ #define gettimeofday os_gettimeofday -/* Type fixups */ -#define mode_t int -#define ssize_t int -#define socklen_t int - -/* Consts */ -#define PIPE_BUF 256 /* What *should* this be on win32? */ -#define MAXDESC 512 /* http://msdn.microsoft.com/en-us/library/kdfaxaay.aspx */ -#define SHUT_RDWR 2 -#define MAX_NAME_LEN _MAX_PATH -#define ETIME 101 -#define PATH_MAX 512 /* it's clearly not _MAX_PATH... other projects seem to use 512 */ -#define EADDRINUSE WSAEADDRINUSE - -#define HOST "unknown-windows-ick" -#define SERVICENAME "Firefly Media Server" #define CONFFILE os_configpath() diff --git a/win32/mt-daapd.vcproj b/win32/mt-daapd.vcproj index 167e5ff5..036ba96c 100644 --- a/win32/mt-daapd.vcproj +++ b/win32/mt-daapd.vcproj @@ -168,6 +168,9 @@ + + @@ -287,6 +290,9 @@ + +