aboutsummaryrefslogtreecommitdiff
path: root/src/mime.c
blob: d90cc3f0eb98882980747b15939721ae8f7acb5d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "spm.h"

Process *file_command(const char *_filename) {
    char *filename = strdup(_filename);
    Process *proc_info = NULL;
    char sh_cmd[PATH_MAX];
    sh_cmd[0] = '\0';
#ifdef __APPLE__
    const char *fmt_cmd = "file -I \"%s\"";
#else  // GNU
    const char *fmt_cmd = "file -E -i \"%s\"";
#endif

    strchrdel(filename, "&;|");
    sprintf(sh_cmd, fmt_cmd, filename);
    shell(&proc_info, SHELL_OUTPUT, sh_cmd);

#ifdef __APPLE__
    // Force BSD command to return non-zero when a file can't be found
    const char *failmsg = ": cannot open";
    if (strstr(proc_info->output, failmsg) != NULL) {
        proc_info->returncode = 1;
    }
#endif
    free(filename);
    return proc_info;
}

Mime *file_mimetype(const char *filename) {
    char **output = NULL;
    char **parts = NULL;
    Mime *type = NULL;
    Process *proc = file_command(filename);

    if (proc->returncode != 0) {
        return NULL;
    }
    output = split(proc->output, ":");
    if (!output || output[1] == NULL) {
        return NULL;
    }
    parts = split(output[1], ";");
    if (!parts || !parts[0] || !parts[1]) {
        return NULL;
    }

    char *what = strdup(parts[0]);
    what = lstrip(what);

    char *charset = strdup(strchr(parts[1], '=') + 1);
    charset = lstrip(charset);
    charset[strlen(charset) - 1] = '\0';

    char *origin = strdup(realpath(filename, NULL));

    type = (Mime *)calloc(1, sizeof(Mime));
    type->origin = origin;
    type->type = strdup(what);
    type->charset = strdup(charset);

    split_free(output);
    split_free(parts);
    return type;
}

void mime_free(Mime *m) {
    if (m != NULL) {
        free(m->origin);
        free(m->type);
        free(m->charset);
        free(m);
    }
}

int file_is_text(const char *filename) {
    int result = 0;
    char *path = normpath(filename);
    Mime *type = file_mimetype(path);
    if (startswith(type->type, "text/") == 0) {
        result = 1;
    }
    free(path);
    mime_free(type);
    return result;
}

int file_is_binary(const char *filename) {
    int result = 0;
    char *path = normpath(filename);
    Mime *type = file_mimetype(path);
    if (startswith(type->type, "application/") == 0 && strcmp(type->charset, "binary") == 0) {
        result = 1;
    }
    free(path);
    mime_free(type);
    return result;
}