aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRodrigo Arias Mallo <rodarima@gmail.com>2025-04-06 21:12:20 +0200
committerRodrigo Arias Mallo <rodarima@gmail.com>2025-05-01 00:56:42 +0200
commit0683b2f5935b6df26723bf89d5b71d002f99aaf2 (patch)
tree304ca6f7833df28ce28eb295c21ced80a0408846 /src
parentbe95429ca287945778d05eb24990f5c08024f901 (diff)
Flatten the conditionals so it is easier to read
Diffstat (limited to 'src')
-rw-r--r--src/misc.h157
1 files changed, 95 insertions, 62 deletions
diff --git a/src/misc.h b/src/misc.h
index 47eb45a3..d936720e 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -41,83 +41,116 @@ static inline void a_Misc_parse_content_disposition(const char *disposition, cha
*filename = NULL;
str = disposition;
+ /* Parse the type (attachment, inline, ...) by reading alpha characters. */
for (s = str; *s && d_isascii((uchar_t)*s) && !iscntrl((uchar_t)*s) &&
!strchr(tspecials_space, *s); s++) ;
- if (type && !(s == str))
- *type = dStrndup(str, s - str);
- if (!*type) {
+ if (s != str) {
+ *type = dStrndup(str, s - str);
+ } else {
+ /* Cannot find type, stop here */
return;
}
+ /* Abort if there are no terminators after the type */
if (!strchr(terminators, *s)) {
dFree(*type);
*type = NULL;
return;
}
- if (*s == ';') {
- bool_t quoted = FALSE;
- const char key[] = "filename";
-
- if ((s = dStriAsciiStr(str, key)) &&
- (s == str || strchr(terminators, s[-1]))) {
- s += sizeof(key) - 1;
- for ( ; *s == ' ' || *s == '\t'; ++s);
- if (*s == '=') {
- size_t len = 0;
- for (++s; *s == ' ' || *s == '\t'; ++s);
- if (*s == '"') {
- quoted = TRUE;
- s++;
- for ( ; *s == '.'; ++s);
- bool_t escaped = FALSE;
- const char *c;
- unsigned int maxlen = strlen(s);
- for (c = s; !(*c == '"' && !escaped); c++) {
- if ((len = c - s + 1) > maxlen) {
- return;
- }
- escaped = *c == '\\';
- }
- *filename = dStrndup(s, len);
- } else {
- for ( ; *s == '.'; ++s);
- if ((len = strcspn(s, terminators))) {
- *filename = dStrndup(s, len);
- }
- }
-
- const char invalid_characters[] = "/\\|~";
- char *s = *filename, *d = *filename;
-
- for ( ; s < *filename + len; s++) {
- if (strchr(invalid_characters, *s)) {
- // If this is a backslash preceding a quote, we want to just
- // skip past it without advancing the destination pointer or
- // copying anything.
- if (!(*s == '\\' && *(s+1) == '"')) {
- *d = '_';
- d++;
- }
- } else if (!quoted && (!d_isascii((uchar_t)*s) || *s == '=')) {
- dFree(*filename);
- *filename = NULL;
- return;
- } else {
- *d = *s;
- d++;
- }
- }
-
- // Truncate filename to deal with the string being shorter if we
- // skipped over any backslash characters in the above loop
- if (s != d) {
- *d = '\0';
- }
+ /* FIXME: what about "attachment ; filename=foo"? */
+
+ /* Stop if the terminator is not ; */
+ if (*s != ';')
+ return;
+
+ /* Now parse the filename */
+ bool_t quoted = FALSE;
+ const char key[] = "filename";
+
+ /* Locate "filename", if not found stop */
+ if ((s = dStriAsciiStr(str, key)) == NULL)
+ return;
+
+ /* Ensure that it is preceded by a terminator if it doesn't start the
+ * disposition??? */
+ if (s != str && !strchr(terminators, s[-1]))
+ return;
+
+ /* Advance s over "filename" (skipping the nul character) */
+ s += sizeof(key) - 1;
+
+ /* Skip blanks like "filename =..." */
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ /* Stop if there is no equal sign */
+ if (*s != '=')
+ return;
+
+ /* Skip over the equal */
+ s++;
+
+ /* Skip blanks after the equal like "filename= ..." */
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ size_t len = 0;
+ if (*s == '"') {
+ quoted = TRUE;
+
+ /* Skip over quote */
+ s++;
+
+ /* Ignore dots at the beginning of the filename */
+ while (*s == '.')
+ s++;
+
+ bool_t escaped = FALSE;
+ const char *c;
+ unsigned int maxlen = strlen(s);
+ for (c = s; !(*c == '"' && !escaped); c++) {
+ if ((len = c - s + 1) > maxlen) {
+ return;
+ }
+ escaped = *c == '\\';
+ }
+ *filename = dStrndup(s, len);
+ } else {
+ for ( ; *s == '.'; ++s);
+ if ((len = strcspn(s, terminators))) {
+ *filename = dStrndup(s, len);
+ }
+ }
+
+ const char invalid_characters[] = "/\\|~";
+ char *f = *filename, *d = *filename;
+
+ for ( ; f < *filename + len; f++) {
+ if (strchr(invalid_characters, *f)) {
+ // If this is a backslash preceding a quote, we want to just
+ // skip past it without advancing the destination pointer or
+ // copying anything.
+ if (!(*f == '\\' && *(f+1) == '"')) {
+ *d = '_';
+ d++;
}
+ } else if (!quoted && (!d_isascii((uchar_t)*f) || *f == '=')) {
+ dFree(*filename);
+ *filename = NULL;
+ return;
+ } else {
+ *d = *f;
+ d++;
}
}
+
+ // Truncate filename to deal with the string being shorter if we
+ // skipped over any backslash characters in the above loop
+ if (f != d) {
+ *d = '\0';
+ }
}
#ifdef __cplusplus