MimeType * mime_find(const RobinFilename *name) { unsigned int u, v; const char *s; size_t len = 0; if (mime_init() == -1) { fprintf(stderr, "cannot load mime.types"); return NULL; } s = (const char *)name->data + name->length; while (s > (const char *)name->data && *--s != '.') len++; if (s < (const char *)name->data + name->length) s++; for (u = 0; u < mime.types.len; u++) for (v = 0; v < mime.types.val[u].exts.len; v++) if (strlen(mime.types.val[u].exts.val[v].ext) == len && strncasecmp(mime.types.val[u].exts.val[v].ext, s, len) == 0) return &mime.types.val[u]; return NULL; }
int main(int argc, char **argv) { struct sigaction sig_stop; struct sigaction sig_time; _main = main_init(argc, argv); _log = log_init(); _main->conf = conf_init(argc, argv); _main->work = work_init(); _main->tcp = tcp_init(); _main->node = node_init(); _main->mime = mime_init(); /* Check configuration */ conf_print(); /* Catch SIG INT */ unix_signal(&sig_stop, &sig_time); /* Fork daemon */ unix_fork(log_console(_log)); /* Increase limits */ unix_limits(_main->conf->cores, CONF_EPOLL_MAX_EVENTS); /* Load mime types */ mime_load(); mime_hash(); /* Prepare TCP daemon */ tcp_start(); /* Drop privileges */ unix_dropuid0(); /* Start worker threads */ work_start(); /* Stop worker threads */ work_stop(); /* Stop TCP daemon */ tcp_stop(); mime_free(); node_free(); tcp_free(); work_free(); conf_free(); log_free(_log); main_free(); return 0; }
char *tg_extension_by_mime (const char *mime_type) { if (!mime_initialized) { mime_init (); } int i; for (i = 0; i < mime_type_number; i++) { if (!strcmp (mime_type_names[i], mime_type)) { return mime_type_extensions[i]; } } return NULL; }
void mime_dump(void) { unsigned int u, v; if (mime_init() == -1) { fprintf(stderr, "cannot load mime.types"); return; } for (u = 0; u < mime.types.len; u++) { printf("%s", mime.types.val[u].type); for (v = 0; v < mime.types.val[u].exts.len; v++) printf("\t%s", mime.types.val[u].exts.val[v].ext); printf("\n"); } }
char *tg_mime_by_filename (const char *filename) { int l = strlen (filename); const char *p = filename - 1 + l; while (p >= filename && *p != '.') { p --; } p ++; if (!mime_initialized) { mime_init (); } static char *def = "application/octet-stream"; if (strlen (p) > 10) { return def; } static char s[11]; #if defined(_MSC_VER) && _MSC_VER >= 1400 strcpy_s(s, 11, p); #else strcpy (s, p); #endif char *q = s; while (*q) { if (*q >= 'A' && *p <= 'Z') { *q = *q + 'z' - 'Z'; } q ++; } int i; for (i = 0; i < mime_type_number; i++) { if (!strcmp (mime_type_extensions[i], s)) { return mime_type_names[i]; } } return def; }
int main( int argc, char **argv ) { // Read any command line arguments from our friend the user. arguments(argc, argv); // Catch some signals so can exit cleanly signal(SIGINT, exit_interrupt); #ifndef WIN32 signal(SIGHUP, exit_interrupt); signal(SIGTERM, exit_interrupt); signal(SIGPIPE, SIG_IGN); if (debug_on) setvbuf(stdout, NULL, _IONBF, 0); #endif printf("%s - Jorgen Lundman v%s %s %s\n\n", argv ? argv[0] : "llink", VERSION, VERSION_STRING, #if WITH_DVDREAD "(libdvdread)" #else #if HAVE_CLINKC "(libdvdnav, ClinkC)" #else "(libdvdnav)" #endif #endif ); lion_buffersize(conf_buffersize); //lion_buffersize(2352); if (lion_init()) { printf("Failed to initialize lion/networking\n"); exit(-1); } debugf("\n"); // Read configuration file, if any // Warning, calls lion_poll until done. conf_init(); debugf("[main] initialising...\n"); // Warning, calls lion_poll until done. mime_init(); // Warning, calls lion_poll until done. skin_init(); ssdp_init(); httpd_init(); request_init(); root_init(); llrar_init(); visited_init(); cgicmd_init(); #ifdef EXTERNAL external_init(); #endif printf("[main] ready!\n"); // Background? #ifndef WIN32 if (!foreground) { if (fork()) exit(0); setsid(); if (conf_pidfile) { FILE *fd; if ((fd = fopen(conf_pidfile, "w"))) { fprintf(fd, "%u\r\n", getpid()); fclose(fd); } } } #endif cupnp_init(); // Scan for media if (conf_xmlscan) { signal(SIGINT, SIG_DFL); xmlscan_run(); do_exit = 1; } query_init(); #ifdef WIN32 SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); #endif // The main loop while ( !do_exit ) { // Was 250,0 - we should probably let users control this in // conf settings. if (lion_poll(0, 1)<0) do_exit=1; request_events(); #ifdef EXTERNAL external_resume(); #endif } printf("\n[main] releasing resources...\n"); query_free(); cupnp_free(); #ifdef EXTERNAL external_free(); #endif root_free(); cgicmd_free(); visited_free(); llrar_free(); request_free(); httpd_free(); ssdp_free(); skin_free(); mime_free(); conf_free(); #ifndef WIN32 // Crashed when releasing spawned processes, until i can fix: lion_free(); #endif debugf("[main] done.\n"); return 0; }
int html_attachment(const char *list, unsigned int y, unsigned int m, unsigned int d, unsigned int n, unsigned int a) { unsigned int aday; char *list_file; off_t idx_offset; int fd, error, got, trunc; idx_msgnum_t m1, m1r; struct idx_message idx_msg; idx_off_t offset; idx_size_t size; struct buffer src, dst; struct mime_ctx mime; char *body, *bend; if (y < MIN_YEAR || y > MAX_YEAR || m < 1 || m > 12 || d < 1 || d > 31 || n < 1 || n > 999999) return html_error("Invalid date or message number"); aday = YMD2ADAY(y - MIN_YEAR, m, d); list_file = concat(MAIL_SPOOL_PATH "/", list, NULL); if (!list_file) return html_error(NULL); fd = idx_open(list); if (fd < 0) { error = errno; free(list_file); return html_error(error == ENOENT ? "No such mailing list" : (error == ESRCH ? "Index needs rebuild" : NULL)); } error = !idx_read_aday_ok(fd, aday, &m1, sizeof(m1)); if (error || m1 < 1 || m1 >= MAX_MAILBOX_MESSAGES) { idx_close(fd); free(list_file); return html_error((error || m1 > 0) ? NULL : "No such message"); } m1r = m1 + n - 2; /* both m1 and n are 1-based; m1r is 0-based */ idx_offset = IDX2MSG(m1r); got = idx_read(fd, idx_offset, &idx_msg, sizeof(idx_msg)); if (got != sizeof(idx_msg)) error = 1; if (idx_close(fd) || error) { free(list_file); return html_error(got ? NULL : "No such message"); } if (y - MIN_YEAR != idx_msg.y || m != idx_msg.m || d != idx_msg.d) { free(list_file); return html_error("No such message"); } offset = idx_msg.offset; size = idx_msg.size; trunc = size > MAX_MESSAGE_SIZE; if (trunc) size = MAX_MESSAGE_SIZE; if (buffer_init(&src, size)) { free(list_file); return html_error(NULL); } fd = open(list_file, O_RDONLY); free(list_file); if (fd < 0) { buffer_free(&src); return html_error("mbox open error"); } error = lseek(fd, offset, SEEK_SET) != offset || read_loop(fd, src.start, size) != size; if (close(fd) || error || mime_init(&mime, &src)) { buffer_free(&src); return html_error("mbox read error"); } if (buffer_init(&dst, size)) { buffer_free(&src); mime_free(&mime); return html_error(NULL); } body = NULL; while (src.end - src.ptr > 9 && *src.ptr != '\n') { switch (*src.ptr) { case 'C': case 'c': mime_decode_header(&mime); continue; } mime_skip_header(&mime); } if (src.ptr >= src.end) { buffer_free(&src); buffer_free(&dst); mime_free(&mime); return html_error(NULL); } if (*src.ptr == '\n') body = ++src.ptr; const char *error_msg = "Attachment not found"; unsigned int attachment_count = 0; if (a) do { if (mime.entities->boundary) { body = mime_next_body_part(&mime); if (!body || body >= src.end) break; body = mime_next_body(&mime); } if (mime.entities->boundary || !is_attachment(&mime) || ++attachment_count != a) body = NULL; if (!body) { bend = mime_skip_body(&mime); if (!bend) break; continue; } int text = !strncasecmp(mime.entities->type, "text/", 5); if (text) { buffer_appends(&dst, "Content-Type: text/plain"); if (mime.entities->charset && enc_allowed_charset(mime.entities->charset)) buffer_appendf(&dst, "; charset=%s", mime.entities->charset); buffer_appendc(&dst, '\n'); } else { buffer_appends(&dst, "Content-Type: application/octet-stream\n"); } buffer_appendf(&dst, "Content-Disposition: %s; filename=\"", text ? "inline" : "attachment"); buffer_append_filename(&dst, mime.entities->filename, text); buffer_appends(&dst, "\"\n"); body = mime_decode_body(&mime, RECODE_NO, &bend); if (trunc && (!body || bend >= src.end)) { error_msg = "Attachment is truncated"; break; } buffer_appendf(&dst, "Content-Length: %llu\n\n", (unsigned long long)(mime.dst.ptr - body)); buffer_append(&dst, body, mime.dst.ptr - body); error_msg = NULL; break; } while (bend < src.end && mime.entities); buffer_free(&src); if (error_msg || mime.dst.error || dst.error) { mime_free(&mime); buffer_free(&dst); return html_error(error_msg); } mime_free(&mime); return html_send(&dst); }
int html_message(const char *list, unsigned int y, unsigned int m, unsigned int d, unsigned int n) { unsigned int aday, n0, n2; char *list_file; off_t idx_offset; int fd, error, got, trunc, prev, next; idx_msgnum_t m0, m1, m1r; struct idx_message idx_msg[3]; idx_off_t offset; idx_size_t size; struct buffer src, dst; struct mime_ctx mime; char *p, *q, *date, *from, *to, *cc, *subject, *body, *bend; if (y < MIN_YEAR || y > MAX_YEAR || m < 1 || m > 12 || d < 1 || d > 31 || n < 1 || n > 999999) return html_error("Invalid date or message number"); aday = YMD2ADAY(y - MIN_YEAR, m, d); list_file = concat(MAIL_SPOOL_PATH "/", list, NULL); if (!list_file) return html_error(NULL); fd = idx_open(list); if (fd < 0) { error = errno; free(list_file); return html_error(error == ENOENT ? "No such mailing list" : (error == ESRCH ? "Index needs rebuild" : NULL)); } error = !idx_read_aday_ok(fd, aday, &m1, sizeof(m1)); if (error || m1 < 1 || m1 >= MAX_MAILBOX_MESSAGES) { idx_close(fd); free(list_file); return html_error((error || m1 > 0) ? NULL : "No such message"); } m1r = m1 + n - (1 + 1); /* both m1 and n are 1-based; m1r is 0-based */ idx_offset = IDX2MSG(m1r); prev = next = 1; if (m1r >= 1) { idx_offset -= sizeof(idx_msg[0]); got = idx_read(fd, idx_offset, &idx_msg, sizeof(idx_msg)); if (got != sizeof(idx_msg)) { error = got != sizeof(idx_msg[0]) * 2; idx_msg[2] = idx_msg[1]; next = 0; } } else { prev = 0; got = idx_read(fd, idx_offset, &idx_msg[1], sizeof(idx_msg[1]) * 2); if (got != sizeof(idx_msg[1]) * 2) { error = got != sizeof(idx_msg[1]); idx_msg[2] = idx_msg[1]; next = 0; } idx_msg[0] = idx_msg[1]; } n0 = n - 1; if (!n0 && prev && !error) { aday = YMD2ADAY(idx_msg[0].y, idx_msg[0].m, idx_msg[0].d); error = !idx_read_aday_ok(fd, aday, &m0, sizeof(m0)); if (m1 > m0) n0 = m1 - m0; else error = 1; } if (idx_close(fd) || error) { free(list_file); return html_error(got ? NULL : "No such message"); } n2 = n + 1; if (idx_msg[2].y != idx_msg[1].y || idx_msg[2].m != m || idx_msg[2].d != d) n2 = 1; if (y - MIN_YEAR != idx_msg[1].y || m != idx_msg[1].m || d != idx_msg[1].d) { free(list_file); return html_error("No such message"); } offset = idx_msg[1].offset; size = idx_msg[1].size; trunc = size > MAX_MESSAGE_SIZE; if (trunc) size = MAX_MESSAGE_SIZE; if (buffer_init(&src, size)) { free(list_file); return html_error(NULL); } fd = open(list_file, O_RDONLY); free(list_file); if (fd < 0) { buffer_free(&src); return html_error("mbox open error"); } error = lseek(fd, offset, SEEK_SET) != offset || read_loop(fd, src.start, size) != size; if (close(fd) || error || mime_init(&mime, &src)) { buffer_free(&src); return html_error("mbox read error"); } if (buffer_init(&dst, size)) { buffer_free(&src); mime_free(&mime); return html_error(NULL); } date = from = to = cc = subject = body = NULL; while (src.end - src.ptr > 9 && *src.ptr != '\n') { switch (*src.ptr) { case 'D': case 'd': if (!strncasecmp(src.ptr, "Date:", 5)) { date = mime_decode_header(&mime); continue; } break; case 'F': case 'f': if (!strncasecmp(src.ptr, "From:", 5)) { from = mime_decode_header(&mime); continue; } break; case 'T': case 't': if (!strncasecmp(src.ptr, "To:", 3)) { to = mime_decode_header(&mime); continue; } break; case 'S': case 's': if (!strncasecmp(src.ptr, "Subject:", 8)) { subject = mime_decode_header(&mime); continue; } break; case 'C': case 'c': if (!strncasecmp(src.ptr, "CC:", 3)) cc = mime_decode_header(&mime); else mime_decode_header(&mime); continue; } mime_skip_header(&mime); } if (src.ptr >= src.end) { buffer_free(&src); buffer_free(&dst); mime_free(&mime); return html_error(NULL); } if (*src.ptr == '\n') body = ++src.ptr; if ((p = subject)) { while ((p = strchr(p, '['))) { if (strncasecmp(++p, list, strlen(list))) continue; q = p + strlen(list); if (*q != ']') continue; if (*++q == ' ') q++; memmove(--p, q, strlen(q) + 1); } } buffer_appends(&dst, "\n"); if (html_flags & HTML_HEADER) { buffer_appends(&dst, "<title>"); buffer_appends_html(&dst, list); if (subject && strlen(subject) > 9) { buffer_appends(&dst, " - "); buffer_appends_html(&dst, subject + 9); } buffer_appends(&dst, "</title>\n"); if (html_flags & HTML_CENSOR) buffer_appends(&dst, "<meta name=\"robots\" content=\"noindex\">\n"); } if (html_flags & HTML_BODY) { unsigned int attachment_count = 0; if (prev) { buffer_appends(&dst, "<a href=\""); if (n == 1) buffer_appendf(&dst, "../../../%u/%02u/%02u/", MIN_YEAR + idx_msg[0].y, idx_msg[0].m, idx_msg[0].d); buffer_appendf(&dst, "%u\">[<prev]</a> ", n0); } if (next) { buffer_appends(&dst, "<a href=\""); if (n2 == 1) buffer_appendf(&dst, "../../../%u/%02u/%02u/", MIN_YEAR + idx_msg[2].y, idx_msg[2].m, idx_msg[2].d); buffer_appendf(&dst, "%u\">[next>]</a> ", n2); } if (idx_msg[1].t.pn) { buffer_appends(&dst, "<a href=\""); if (idx_msg[1].t.py != idx_msg[1].y || idx_msg[1].t.pm != idx_msg[1].m || idx_msg[1].t.pd != idx_msg[1].d) buffer_appendf(&dst, "../../../%u/%02u/%02u/", MIN_YEAR + idx_msg[1].t.py, idx_msg[1].t.pm, idx_msg[1].t.pd); buffer_appendf(&dst, "%u\">[<thread-prev]</a> ", idx_msg[1].t.pn); } if (idx_msg[1].t.nn) { buffer_appends(&dst, "<a href=\""); if (idx_msg[1].t.ny != idx_msg[1].y || idx_msg[1].t.nm != idx_msg[1].m || idx_msg[1].t.nd != idx_msg[1].d) buffer_appendf(&dst, "../../../%u/%02u/%02u/", MIN_YEAR + idx_msg[1].t.ny, idx_msg[1].t.nm, idx_msg[1].t.nd); buffer_appendf(&dst, "%u\">[thread-next>]</a> ", idx_msg[1].t.nn); } buffer_appends(&dst, "<a href=\".\">[day]</a>" " <a href=\"..\">[month]</a>" " <a href=\"../..\">[year]</a>" " <a href=\"../../..\">[list]</a>\n"); buffer_appends(&dst, "<pre style=\"white-space: pre-wrap\">\n"); if (date) buffer_append_header(&dst, date); if (from) buffer_append_header(&dst, from); if (to) buffer_append_header(&dst, to); if (cc) buffer_append_header(&dst, cc); if (subject) buffer_append_header(&dst, subject); if (!(html_flags & HTML_CENSOR)) do { if (mime.entities->boundary) { body = mime_next_body_part(&mime); if (!body || body >= src.end) break; body = mime_next_body(&mime); } if (mime.entities->boundary) body = NULL; if (!body) { bend = mime_skip_body(&mime); if (!bend) break; continue; } /* mime_decode_body() will break mime vars, so, * remember them now */ char *filename = mime.entities->filename; char *type = mime.entities->type; const int isattachment = is_attachment(&mime); const int isinline = is_inline(&mime); int skip = 0; body = mime_decode_body(&mime, isattachment ? RECODE_NO : RECODE_YES, &bend); if (!body) break; if (bend >= src.end) skip = trunc; bend = src.ptr; if (!skip && isattachment) { int text = !strncasecmp(type, "text/", 5); attachment_count++; buffer_appendf(&dst, "\n<span style=\"font-family: times;\"><strong>" "%s attachment \"</strong><a href=\"%u/%u\"%s>", text ? "View" : "Download", n, attachment_count, text ? "" : " rel=\"nofollow\" download"); if (filename) buffer_appends_html(&dst, filename); buffer_appends(&dst, "</a><strong>\" of type \"</strong>"); buffer_appends_html(&dst, type); buffer_appends(&dst, "<strong>\""); if (body) buffer_appendf(&dst, " (%llu bytes)", (unsigned long long)(mime.dst.ptr - body)); buffer_appends(&dst, "</strong></span>\n"); continue; } else if (!isinline) { skip = 1; } else { skip = 0; /* do not skip non-attachments */ } if (skip) { buffer_appends(&dst, "\n<span style=\"font-family: times;\"><strong>" "Content of type \"</strong>"); buffer_appends_html(&dst, type); buffer_appends(&dst, "<strong>\" skipped</strong></span>\n"); continue; } /* inline */ buffer_appendc(&dst, '\n'); buffer_append_html_generic(&dst, body, mime.dst.ptr - body, 0, 1); mime.dst.ptr = body; } while (bend < src.end && mime.entities); if ((html_flags & HTML_CENSOR) || trunc) buffer_appendf(&dst, "\n<span style=\"font-family: times;\"><strong>" "Content %s</strong></span>\n", (html_flags & HTML_CENSOR) ? "removed" : "truncated"); buffer_appends(&dst, "</pre>\n"); } buffer_free(&src); if (mime.dst.error || dst.error) { mime_free(&mime); buffer_free(&dst); return html_error(NULL); } mime_free(&mime); return html_send(&dst); }