00001
00007 #include <errno.h>
00008 #include <stdint.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <stdbool.h>
00012 #include <stdlib.h>
00013 #include <limits.h>
00014
00015 #include "asf.h"
00016 #include "db5_types.h"
00017 #include "file.h"
00018 #include "logger.h"
00019 #include "check.h"
00020 #include "wstring.h"
00021
00023 #define ASF_MAGIC 0x3026b275
00024
00026 #define SIZEOF_TAG 34
00027
00029 typedef unsigned char guid_t[16];
00030
00032 const guid_t title_artist = { 0x33, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C };
00033
00037 typedef struct asf_tag_t
00038 {
00040 guid_t guid;
00042 uint32_t record_size;
00044 uint32_t reserved_1;
00046 uint16_t title_size;
00048 uint16_t artist_size;
00049 } asf_tag;
00050
00051
00059 static inline bool compare4(const void *item1, const void *item2, const size_t size)
00060 {
00061 int i;
00062
00063 for(i=0; i < size/sizeof(uint32_t); i++)
00064 {
00065 if (((uint32_t *)item1)[i] != ((uint32_t *)item2)[i])
00066 {
00067 return false;
00068 }
00069 }
00070
00071 return true;
00072 }
00073
00080 static size_t asf_find_header(const guid_t *guid, const char *buffer, const size_t len)
00081 {
00082 size_t result;
00083
00084 check(guid != NULL);
00085 check(buffer != NULL);
00086 check(len > 0);
00087
00088
00089 if (len < sizeof(guid_t))
00090 {
00091 add_log(ADDLOG_DEBUG, "[asf]find_header", "not enougth data to find header, len=%u\n", len);
00092 return len;
00093 }
00094
00095 for(result = 0; result <= (len - sizeof(guid_t)); result++)
00096 {
00097 if (compare4(buffer+result, guid, sizeof(guid_t)))
00098 {
00099 return result;
00100 }
00101 }
00102
00103 return len;
00104 }
00105
00106 bool asf_generate_row(const char *filename, db5_row *row)
00107 {
00108 FILE *wma;
00109 size_t read;
00110 size_t position;
00111 asf_tag *header;
00112 char *artist;
00113 char *title;
00114
00115 check(filename != NULL);
00116 check(row != NULL);
00117
00118 add_log(ADDLOG_DEBUG, "[asf]gen_row", "preparing information for '%s'\n", filename);
00119
00120
00121 row->bitrate = 128000;
00122 row->samplerate = 44100;
00123
00124 #ifndef NOJOKE
00125 row->year = 1984;
00126 #endif
00127
00128 strncpy(row->album, "Microsoft WMA", membersizeof(db5_row, album)/2);
00129 strncpy(row->genre, "WMA file", membersizeof(db5_row, genre)/2);
00130
00131 wma = fopen(filename, "rb");
00132 if (wma == NULL)
00133 {
00134 add_log(ADDLOG_RECOVER, "[asf]gen_row", "unable to open file '%s': %s\n", filename, strerror(errno));
00135 return true;
00136 }
00137
00138 read = fread(file_common_buffer, 1, sizeof(file_common_buffer), wma);
00139 if (read == 0)
00140 {
00141 add_log(ADDLOG_RECOVER, "[asf]gen_row", "unable to read file '%s'\n", filename);
00142 fclose(wma);
00143 return true;
00144 }
00145
00146 fclose(wma);
00147
00148 row->filesize = file_filesize(filename);
00149 row->duration = row->filesize / (row->bitrate / 8);
00150
00151 position = asf_find_header(&title_artist, file_common_buffer, read);
00152 if (position >= read)
00153 {
00154 add_log(ADDLOG_NOTICE, "[asf]gen_row", "unable to find tag in file '%s'\n", filename);
00155 return true;
00156 }
00157
00158 add_log(ADDLOG_DUMP, "[asf]gen_row", "asf header found at file offset 0x%08x\n", position);
00159
00160 header = (asf_tag *)(file_common_buffer+position);
00161
00162 if (SIZEOF_TAG + header->title_size + header->artist_size != header->record_size)
00163 {
00164 add_log(ADDLOG_NOTICE, "[asf]gen_row", "tag size is invalid in file '%s'\n", filename);
00165 return true;
00166 }
00167
00168 if ((position + header->record_size) > read)
00169 {
00170 add_log(ADDLOG_NOTICE, "[asf]gen_row", "tag seems too big in filename '%s'\n", filename);
00171 return true;
00172 }
00173
00174
00175 artist = (char *)malloc(header->artist_size);
00176 if (artist == NULL)
00177 {
00178 add_log(ADDLOG_RECOVER, "[asf]gen_row", "not enougth memory, artist length=%u\n", header->artist_size);
00179 }
00180 else
00181 {
00182 memcpy(artist, file_common_buffer + position + SIZEOF_TAG + header->title_size, header->artist_size);
00183 ws_wstoa(artist, header->artist_size);
00184 strncpy(row->artist, artist, membersizeof(db5_row, artist)/2);
00185 free(artist);
00186 }
00187
00188
00189 title = (char *)malloc(header->title_size);
00190 if (title == NULL)
00191 {
00192 add_log(ADDLOG_RECOVER, "[asf]gen_row", "not enougth memory, title length=%u\n", header->title_size);
00193 }
00194 else
00195 {
00196 memcpy(title, file_common_buffer + position + SIZEOF_TAG, header->title_size);
00197 ws_wstoa(title, header->title_size);
00198 strncpy(row->title, title, membersizeof(db5_row, title)/2);
00199 free(title);
00200 }
00201
00202 return true;
00203 }
00204