summaryrefslogtreecommitdiffstats
path: root/apps/cuesheet.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/cuesheet.c')
-rw-r--r--apps/cuesheet.c135
1 files changed, 93 insertions, 42 deletions
diff --git a/apps/cuesheet.c b/apps/cuesheet.c
index be89ef96cf..bbdc93746e 100644
--- a/apps/cuesheet.c
+++ b/apps/cuesheet.c
@@ -58,28 +58,28 @@ static bool search_for_cuesheet(const char *path, struct cuesheet_file *cue_file
slash_cuepath = &cuepath[slash - path];
dot = strrchr(slash_cuepath, '.');
if (dot)
- strlcpy(dot, ".cue", MAX_PATH - (dot-cuepath));
+ strmemccpy(dot, ".cue", MAX_PATH - (dot-cuepath));
if (!dot || !file_exists(cuepath))
{
strcpy(cuepath, CUE_DIR);
if (strlcat(cuepath, slash, MAX_PATH) >= MAX_PATH)
goto skip; /* overflow */
- char *dot = strrchr(cuepath, '.');
+ dot = strrchr(cuepath, '.');
strcpy(dot, ".cue");
if (!file_exists(cuepath))
{
skip:
if ((len+4) >= MAX_PATH)
return false;
- strlcpy(cuepath, path, MAX_PATH);
+ strmemccpy(cuepath, path, MAX_PATH);
strlcat(cuepath, ".cue", MAX_PATH);
if (!file_exists(cuepath))
return false;
}
}
- strlcpy(cue_file->path, cuepath, MAX_PATH);
+ strmemccpy(cue_file->path, cuepath, MAX_PATH);
return true;
}
@@ -91,7 +91,7 @@ bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cu
cue_file->pos = track_id3->embedded_cuesheet.pos;
cue_file->size = track_id3->embedded_cuesheet.size;
cue_file->encoding = track_id3->embedded_cuesheet.encoding;
- strlcpy(cue_file->path, track_id3->path, MAX_PATH);
+ strmemccpy(cue_file->path, track_id3->path, MAX_PATH);
return true;
}
@@ -123,6 +123,7 @@ static unsigned long parse_cue_index(const char *line)
/* assumes strncmp(line, "INDEX 01", 8) & NULL terminated string */
/* INDEX 01 MM:SS:FF\0 (00:00:00\0 - 99:99:99\0)*/
const unsigned field_m[3] = {60 * 1000, 1000, 13}; /* MM:SS:~FF*/
+ const unsigned field_max[3] = {30000, 59, 74}; /* MM, SS, FF */
const char f_sep = ':';
int field = -1;
unsigned long offset = 0; /* ms from start of track */
@@ -138,7 +139,7 @@ static unsigned long parse_cue_index(const char *line)
while (isdigit(*line))
{
value = 10 * value + (*line - '0');
- if (value > 99) /* Sanity check bail early */
+ if (field >= 0 && value > field_max[field]) /* Sanity check bail early */
return 0;
line++;
}
@@ -165,6 +166,38 @@ static unsigned long parse_cue_index(const char *line)
return offset;
}
+enum eCS_SUPPORTED_TAGS {
+ eCS_TRACK = 0, eCS_INDEX_01, eCS_TITLE,
+ eCS_PERFORMER, eCS_SONGWRITER, eCS_FILE,
+ eCS_COUNT_TAGS_COUNT, eCS_NOTFOUND = -1
+};
+
+static enum eCS_SUPPORTED_TAGS cuesheet_tag_get_option(const char *option)
+{
+ #define CS_OPTN(str) {str, sizeof(str)-1}
+ static const struct cs_option_t {
+ const char *str;
+ const int len;
+ } cs_options[eCS_COUNT_TAGS_COUNT + 1] = {
+ [eCS_TRACK] = CS_OPTN("TRACK"),
+ [eCS_INDEX_01] = CS_OPTN("INDEX 01"),
+ [eCS_TITLE] =CS_OPTN("TITLE"),
+ [eCS_PERFORMER] =CS_OPTN("PERFORMER"),
+ [eCS_SONGWRITER] =CS_OPTN("SONGWRITER"),
+ [eCS_FILE] =CS_OPTN("FILE"),
+ [eCS_COUNT_TAGS_COUNT] = {NULL, 0} /*SENTINEL*/
+ };
+
+ const struct cs_option_t *op;
+ for (int i=0; ((op=&cs_options[i]))->str != NULL; i++)
+ {
+ if (strncmp(option, op->str, op->len) == 0)
+ return i;
+ }
+ return eCS_NOTFOUND;
+#undef CS_OPTN
+}
+
/* parse cuesheet "cue_file" and store the information in "cue" */
bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
{
@@ -190,22 +223,25 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
/* Look for a Unicode BOM */
unsigned char bom_read = 0;
- read(fd, line, BOM_UTF_8_SIZE);
- if(!memcmp(line, BOM_UTF_8, BOM_UTF_8_SIZE))
- {
- char_enc = CHAR_ENC_UTF_8;
- bom_read = BOM_UTF_8_SIZE;
- }
- else if(!memcmp(line, BOM_UTF_16_LE, BOM_UTF_16_SIZE))
- {
- char_enc = CHAR_ENC_UTF_16_LE;
- bom_read = BOM_UTF_16_SIZE;
- }
- else if(!memcmp(line, BOM_UTF_16_BE, BOM_UTF_16_SIZE))
+ if (read(fd, line, BOM_UTF_8_SIZE) > 0)
{
- char_enc = CHAR_ENC_UTF_16_BE;
- bom_read = BOM_UTF_16_SIZE;
+ if(!memcmp(line, BOM_UTF_8, BOM_UTF_8_SIZE))
+ {
+ char_enc = CHAR_ENC_UTF_8;
+ bom_read = BOM_UTF_8_SIZE;
+ }
+ else if(!memcmp(line, BOM_UTF_16_LE, BOM_UTF_16_SIZE))
+ {
+ char_enc = CHAR_ENC_UTF_16_LE;
+ bom_read = BOM_UTF_16_SIZE;
+ }
+ else if(!memcmp(line, BOM_UTF_16_BE, BOM_UTF_16_SIZE))
+ {
+ char_enc = CHAR_ENC_UTF_16_BE;
+ bom_read = BOM_UTF_16_SIZE;
+ }
}
+
if (bom_read < BOM_UTF_8_SIZE)
lseek(fd, cue_file->pos + bom_read, SEEK_SET);
if (is_embedded)
@@ -245,11 +281,16 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
}
s = skip_whitespace(line);
- if (!strncmp(s, "TRACK", 5))
+/* RECOGNIZED TAGS ***********************
+* eCS_TRACK = 0, eCS_INDEX_01, eCS_TITLE,
+* eCS_PERFORMER, eCS_SONGWRITER, eCS_FILE,
+*/
+ enum eCS_SUPPORTED_TAGS option = cuesheet_tag_get_option(s);
+ if (option == eCS_TRACK)
{
cue->track_count++;
}
- else if (!strncmp(s, "INDEX 01", 8))
+ else if (option == eCS_INDEX_01)
{
#if 0
s = strchr(s,' ');
@@ -265,10 +306,7 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
cue->tracks[cue->track_count-1].offset = parse_cue_index(s);
#endif
}
- else if (!strncmp(s, "TITLE", 5)
- || !strncmp(s, "PERFORMER", 9)
- || !strncmp(s, "SONGWRITER", 10)
- || !strncmp(s, "FILE", 4))
+ else if (option != eCS_NOTFOUND)
{
char *dest = NULL;
char *string = get_string(s);
@@ -278,24 +316,24 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
size_t count = MAX_NAME*3 + 1;
size_t count8859 = MAX_NAME;
- switch (*s)
+ switch (option)
{
- case 'T': /* TITLE */
+ case eCS_TITLE: /* TITLE */
dest = (cue->track_count <= 0) ? cue->title :
cue->tracks[cue->track_count-1].title;
break;
- case 'P': /* PERFORMER */
+ case eCS_PERFORMER: /* PERFORMER */
dest = (cue->track_count <= 0) ? cue->performer :
cue->tracks[cue->track_count-1].performer;
break;
- case 'S': /* SONGWRITER */
+ case eCS_SONGWRITER: /* SONGWRITER */
dest = (cue->track_count <= 0) ? cue->songwriter :
cue->tracks[cue->track_count-1].songwriter;
break;
- case 'F': /* FILE */
+ case eCS_FILE: /* FILE */
if (is_embedded || cue->track_count > 0)
break;
@@ -303,6 +341,16 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
count = MAX_PATH;
count8859 = MAX_PATH/3;
break;
+ case eCS_TRACK:
+ /*Fall-Through*/
+ case eCS_INDEX_01:
+ /*Fall-Through*/
+ case eCS_COUNT_TAGS_COUNT:
+ /*Fall-Through*/
+ case eCS_NOTFOUND: /*Shouldn't happen*/
+ logf(HZ * 2, "Bad Tag %d @ %s", (int) option, __func__);
+ dest = NULL;
+ break;
}
if (dest)
@@ -315,10 +363,11 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
}
else
{
- strlcpy(dest, string, count);
+ strmemccpy(dest, string, count);
}
}
}
+
if (is_embedded)
{
bytes_left -= line_len;
@@ -337,7 +386,7 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
strcpy(cue->file, cue->path);
char *slash = strrchr(cue->file, '/');
if (!slash++) slash = cue->file;
- strlcpy(slash, line, MAX_PATH - (slash - cue->file));
+ strmemccpy(slash, line, MAX_PATH - (slash - cue->file));
}
/* If some songs don't have performer info, we copy the cuesheet performer */
@@ -345,10 +394,10 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
for (i = 0; i < cue->track_count; i++)
{
if (*(cue->tracks[i].performer) == '\0')
- strlcpy(cue->tracks[i].performer, cue->performer, MAX_NAME*3);
+ strmemccpy(cue->tracks[i].performer, cue->performer, MAX_NAME*3);
if (*(cue->tracks[i].songwriter) == '\0')
- strlcpy(cue->tracks[i].songwriter, cue->songwriter, MAX_NAME*3);
+ strmemccpy(cue->tracks[i].songwriter, cue->songwriter, MAX_NAME*3);
}
return true;
@@ -392,7 +441,7 @@ static const char* list_get_name_cb(int selected_item,
struct cuesheet *cue = (struct cuesheet *)data;
if (selected_item & 1)
- strlcpy(buffer, cue->tracks[selected_item/2].title, buffer_len);
+ strmemccpy(buffer, cue->tracks[selected_item/2].title, buffer_len);
else
snprintf(buffer, buffer_len, "%02d. %s", selected_item/2+1,
cue->tracks[selected_item/2].performer);
@@ -432,7 +481,7 @@ void browse_cuesheet(struct cuesheet *cue)
{
gui_synclist_draw(&lists);
action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (gui_synclist_do_button(&lists, &action, LIST_WRAP_UNLESS_HELD))
+ if (gui_synclist_do_button(&lists, &action))
continue;
switch (action)
{
@@ -459,7 +508,7 @@ void browse_cuesheet(struct cuesheet *cue)
/* check that this cue is the same one that would be found by
a search from playback */
char file[MAX_PATH];
- strlcpy(file, cue->file, MAX_PATH);
+ strmemccpy(file, cue->file, MAX_PATH);
if (!strcmp(cue->path, file) || /* if embedded */
(search_for_cuesheet(file, &cue_file) &&
@@ -474,6 +523,8 @@ void browse_cuesheet(struct cuesheet *cue)
case ACTION_STD_CANCEL:
done = true;
+ default:
+ break;
}
}
}
@@ -486,7 +537,7 @@ bool display_cuesheet_content(char* filename)
if (!cue || bufsize < sizeof(struct cuesheet))
return false;
- strlcpy(cue_file.path, filename, MAX_PATH);
+ strmemccpy(cue_file.path, filename, MAX_PATH);
cue_file.pos = 0;
cue_file.size = 0;
@@ -516,12 +567,12 @@ bool curr_cuesheet_skip(struct cuesheet *cue, int direction, unsigned long curr_
if (!(direction <= 0 && track == 0))
{
/* If skipping forward, skip to next cuesheet segment. If skipping
- backward before DEFAULT_SKIP_TRESH milliseconds have elapsed, skip
+ backward before DEFAULT_SKIP_THRESH milliseconds have elapsed, skip
to previous cuesheet segment. If skipping backward after
- DEFAULT_SKIP_TRESH seconds have elapsed, skip to the start of the
+ DEFAULT_SKIP_THRESH seconds have elapsed, skip to the start of the
current cuesheet segment */
if (direction == 1 ||
- ((curr_pos - cue->tracks[track].offset) < DEFAULT_SKIP_TRESH))
+ ((curr_pos - cue->tracks[track].offset) < DEFAULT_SKIP_THRESH))
{
track += direction;
}