📄 mms_util.c
字号:
static int lockfile(int fd, int shouldblock)
{
int n, stop;
unsigned flg = shouldblock ? 0 : LOCK_NB;
do {
n = flock(fd, LOCK_EX|flg);
if (n < 0) {
if (errno == EINTR)
stop = 0;
else
stop = 1;
} else
stop = 1;
} while (!stop);
return (n == 0) ? 0 : errno;
}
static int check_lock(int fd, char *fname)
{
struct stat fs = {0}, ds = {0};
/* You might grab a lock on a file, but the file
* might be changed just before you grabbed the lock. Detect that and fail..
*/
if (fstat(fd, &ds) < 0 ||
stat(fname, &fs) < 0 ||
ds.st_nlink != fs.st_nlink ||
memcmp(&ds.st_dev,&fs.st_dev, sizeof ds.st_dev) != 0 ||
memcmp(&ds.st_ino,&fs.st_ino, sizeof ds.st_ino) != 0 ||
ds.st_uid != fs.st_uid ||
ds.st_gid != fs.st_gid ||
ds.st_size != fs.st_size)
return -1;
else
return 0;
}
int mm_lockfile(int fd, char *fname, int shouldblock)
{
int ret = lockfile(fd,shouldblock);
if (ret != 0 ||
(ret = check_lock(fd,fname)) != 0)
return ret;
return 0;
}
void mms_collect_envdata_from_msgheaders(List *mh, List **xto,
Octstr **subject,
Octstr **otransid, time_t *expiryt,
time_t *deliveryt, long default_msgexpiry)
{
Octstr *s;
List *l = http_header_find_all(mh, "To");
if (l) {
int i, n;
for (i = 0, n = gwlist_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
gwlist_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
l = http_header_find_all(mh, "Cc");
if (l) {
int i, n;
for (i = 0, n = gwlist_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
gwlist_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
l = http_header_find_all(mh, "Bcc");
if (l) {
int i, n;
for (i = 0, n = gwlist_len(l); i<n; i++) {
Octstr *name, *value;
http_header_get(l, i, &name, &value);
gwlist_append(*xto, value);
octstr_destroy(name);
}
http_destroy_headers(l);
}
/* Find expiry and delivery times */
if (expiryt) {
s = http_header_value(mh, octstr_imm("X-Mms-Expiry"));
if (s) {
*expiryt = date_parse_http(s);
octstr_destroy(s);
} else
*expiryt = time(NULL) + default_msgexpiry;
}
if (deliveryt) {
s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time"));
if (s) {
*deliveryt = date_parse_http(s);
octstr_destroy(s);
} else
*deliveryt = 0;
}
if (subject)
*subject = http_header_value(mh, octstr_imm("Subject"));
if (otransid)
*otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID"));
}
unsigned long _mshash(char *s)
{
unsigned h = 0;
while (*s) {
unsigned int ch = tolower(*s);
s++;
h += ((unsigned)(ch) << 4) + 1249;
}
return h;
}
int isphonenum(Octstr *s)
{
int i = 0, n = octstr_len(s);
char *cs;
if (s && octstr_len(s) >= 1 &&
octstr_get_cstr(s)[0] == '+')
i++;
for ( cs = octstr_get_cstr(s); i<n; i++)
if (!gw_isdigit(cs[i]))
return 0;
return 1;
}
/* Doesn't handle IP addresses very well */
void _mms_fixup_address(Octstr *address, char *unified_prefix)
{
int i;
Octstr *typ;
if (!address) return;
i = octstr_search_char(address, '@', 0);
if (i>0) /* an email address. */
return;
i = octstr_search(address, octstr_imm("/TYPE="), 0);
if (i > 0) {
typ = octstr_copy(address, i, octstr_len(address));
octstr_delete(address, i, octstr_len(address));
} else
typ = NULL;
if (isphonenum(address) || (typ && octstr_str_compare(typ, "/TYPE=PLMN") == 0)) {
if (unified_prefix)
normalize_number(unified_prefix, &address);
octstr_append(address, octstr_imm("/TYPE=PLMN"));
} else if (typ)
octstr_append(address, typ);
else
octstr_append(address, octstr_imm("@unknown"));
octstr_destroy(typ);
}
/* compare, reversed result! */
static int comp_fn(void *item, void *pattern)
{
return (octstr_case_compare(item, pattern) == 0) ? 1 : 0;
}
int is_allowed_host(Octstr *host, Octstr *host_list)
{
List *l;
int ret;
gw_assert(host_list);
gw_assert(host);
l = octstr_split(host_list, octstr_imm(";"));
ret = (gwlist_search(l, host, comp_fn) != NULL) ? 1 : 0;
gwlist_destroy(l, (void *)octstr_destroy);
return ret;
}
#define SHELLCHARS "'|\"()[]{}$&!?*><%`\n \t\\"
void escape_shell_chars(Octstr *str)
{
Octstr *tmp;
int i, n;
octstr_strip_blanks(str);
tmp = octstr_duplicate(str);
octstr_delete(str, 0, octstr_len(str));
for (i = 0, n = octstr_len(tmp); i < n; i++) {
int ch = octstr_get_char(tmp,i);
if (strchr(SHELLCHARS, ch) != NULL)
octstr_append_char(str, '\\');
octstr_append_char(str, ch);
}
octstr_destroy(tmp);
}
int parse_cgivars(List *request_headers, Octstr *request_body,
List **cgivars, List **cgivar_ctypes)
{
Octstr *ctype = NULL, *charset = NULL;
int ret = 0;
if (request_body == NULL ||
octstr_len(request_body) == 0 || cgivars == NULL)
return 0; /* Nothing to do, this is a normal GET request. */
http_header_get_content_type(request_headers, &ctype, &charset);
if (*cgivars == NULL)
*cgivars = gwlist_create();
if (*cgivar_ctypes == NULL)
*cgivar_ctypes = gwlist_create();
if (!ctype) {
warning(0, "MMS: Parse CGI Vars: Missing Content Type!");
ret = -1;
goto done;
}
if (octstr_case_compare(ctype, octstr_imm("application/x-www-form-urlencoded")) == 0) {
/* This is a normal POST form */
List *l = octstr_split(request_body, octstr_imm("&"));
Octstr *v;
while ((v = gwlist_extract_first(l)) != NULL) {
List *r = octstr_split(v, octstr_imm("="));
if (gwlist_len(r) == 0)
warning(0, "MMS: Parse CGI Vars: Missing CGI var name/value in POST data: %s",
octstr_get_cstr(request_body));
else {
HTTPCGIVar *x = gw_malloc(sizeof *x);
x->name = gwlist_extract_first(r);
x->value = gwlist_extract_first(r);
if (!x->value)
x->value = octstr_imm("");
octstr_strip_blanks(x->name);
octstr_strip_blanks(x->value);
octstr_url_decode(x->name);
octstr_url_decode(x->value);
gwlist_append(*cgivars, x);
}
octstr_destroy(v);
gwlist_destroy(r, octstr_destroy_item);
}
gwlist_destroy(l, NULL);
} else if (octstr_case_compare(ctype, octstr_imm("multipart/form-data")) == 0) {
/* multi-part form data */
MIMEEntity *m = mime_http_to_entity(request_headers, request_body);
int i, n;
if (!m) {
warning(0, "MMS: Parse CGI Vars: Failed to parse multipart/form-data body: %s",
octstr_get_cstr(request_body));
ret = -1;
goto done;
}
/* Go through body parts, pick out what we need. */
for (i = 0, n = mime_entity_num_parts(m); i < n; i++) {
MIMEEntity *mp = mime_entity_get_part(m, i);
List *headers = mime_entity_headers(mp);
Octstr *body = mime_entity_body(mp);
Octstr *ct = http_header_value(headers,
octstr_imm("Content-Type"));
Octstr *cd = http_header_value(headers,
octstr_imm("Content-Disposition"));
Octstr *name = http_get_header_parameter(cd, octstr_imm("name"));
if (name) {
HTTPCGIVar *x = gw_malloc(sizeof *x);
/* Strip quotes */
if (octstr_get_char(name, 0) == '"') {
octstr_delete(name, 0, 1);
octstr_truncate(name, octstr_len(name) - 1);
}
x->name = octstr_duplicate(name);
x->value = octstr_duplicate(body);
gwlist_append(*cgivars, x);
if (ct) { /* If the content type is set, use it. */
x = gw_malloc(sizeof *x);
x->name = octstr_duplicate(name);
x->value = octstr_duplicate(ct);
gwlist_append(*cgivar_ctypes, x);
}
octstr_destroy(name);
}
octstr_destroy(ct);
octstr_destroy(cd);
octstr_destroy(body);
http_destroy_headers(headers);
mime_entity_destroy(mp);
}
mime_entity_destroy(m);
} else /* else it is nothing that we know about, so simply go away... */
ret = -1;
done:
octstr_destroy(ctype);
octstr_destroy(charset);
return ret;
}
/* get content-ID header, fix: WAP decoder may leave \" at beginning */
Octstr *_x_get_content_id(List *headers)
{
Octstr *cid = http_header_value(headers, octstr_imm("Content-ID"));
if (cid)
if (octstr_get_char(cid, 0) == '"' &&
octstr_get_char(cid, octstr_len(cid) - 1) != '"')
octstr_delete(cid, 0,1);
return cid;
}
/* Utility: Take a header list, remove any boundary parameter from the content-type
* element. We don't want this in the WSP packed content.
*/
void strip_boundary_element(List *headers, char *s)
{
Octstr *ctype = NULL, *params = NULL;
Octstr *value;
int n;
gw_assert(headers);
if ((n = get_content_type(headers, &ctype, ¶ms)) < 0) {
octstr_destroy(ctype);
ctype = NULL; /* no ctype found, so do not replace it! */
} else if (ctype &&
DRM_CONTENT_TYPE(ctype)) {
octstr_destroy(ctype);
ctype = NULL; /* leave drm alone! */
}
if (s) {/* we are replacing the content type as well as stripping */
octstr_destroy(ctype);
ctype = octstr_create(s);
}
if (params && ctype) {
List *h = get_value_parameters(params);
Octstr *ps;
http_header_remove_all(h,"boundary"); /* We don't need the boundary param if it is there. */
ps = make_value_parameters(h);
value = octstr_format("%S%s%S", ctype,
(ps && octstr_len(ps) > 0) ? "; " : "",
ps);
octstr_destroy(ps);
http_destroy_headers(h);
} else
value = ctype;
if (value) {
http_header_remove_all(headers, "Content-Type");
http_header_add(headers, "Content-Type", octstr_get_cstr(value));
}
if (ctype != value)
octstr_destroy(ctype);
octstr_destroy(value);
}
/* Mapping file extensions to content types. */
static struct {
char *ctype, *file_ext;
} exts[] = {
{"text/plain", "txt"},
{"image/jpeg", "jpg"},
{"image/jpeg", "jpeg"},
{"image/png", "png"},
{"image/tiff", "tiff"},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -