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 @@
+
+