static char rcsid[] = "@(#)$Id: url_path.c,v 1.5 2006/05/07 08:35:31 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.5 $ $State: Exp $ * * Author: Kari Hurtta * or Kari Hurtta *****************************************************************************/ #include "def_url.h" #include "s_me.h" DEBUG_VAR(Debug,__FILE__,"url"); static unsigned char * s2us P_((char *str)); static unsigned char * s2us(str) char *str; { return (unsigned char *)str; } static struct url_path_elem * alloc_url_path_elem P_((void)); static struct url_path_elem * alloc_url_path_elem() { struct url_path_elem * ret = safe_malloc (sizeof (*ret)); /* bzero is defined hdrs/defs.h */ bzero((void *)ret,sizeof (*ret)); ret->magic = URL_path_elem_magic; ret->elem = NULL; ret->trailing_slash = 0; return ret; } static void free_url_path_elem P_((struct url_path_elem **ptr)); static void free_url_path_elem(ptr) struct url_path_elem **ptr; { if (URL_path_elem_magic != (*ptr)->magic) panic("URL PANIC",__FILE__,__LINE__,"free_url_path_elem", "bad magic number",0); if ((*ptr)->elem) free_url_element(& ((*ptr)->elem)); (*ptr)->trailing_slash = 0; (*ptr)->magic = 0; /* Invalidate */ free(*ptr); *ptr = NULL; } struct url_path_elem * dup_url_path_elem P_((struct url_path_elem *ptr)); struct url_path_elem * dup_url_path_elem(ptr) struct url_path_elem *ptr; { struct url_path_elem * ret = alloc_url_path_elem(); if (URL_path_elem_magic != ptr->magic) panic("URL PANIC",__FILE__,__LINE__,"dup_url_path_elem", "bad magic number",0); if (ptr->elem) ret->elem = dup_url_element(ptr->elem); ret->trailing_slash = ptr->trailing_slash; return ret; } enum elem_class { p_error, p_normal, p_this, p_up } classify_url_path_elem P_((struct url_path_elem *ptr)); enum elem_class classify_url_path_elem(ptr) struct url_path_elem *ptr; { CONST struct string * parsed; uint16 ch; int len; if (URL_path_elem_magic != ptr->magic) panic("URL PANIC",__FILE__,__LINE__,"classify_url_path_elem", "bad magic number",0); if (!ptr->elem) panic("URL PANIC",__FILE__,__LINE__,"classify_url_path_elem", "Is root element?",0); parsed = parsed_from_element(ptr->elem,NULL); if (!parsed) return p_error; len = string_len(parsed); if (len < 1) return p_normal; ch = give_unicode_from_string(parsed,0); if (0x002E /* . */ != ch) return p_normal; if (1 == len) return p_this; /* "." */ ch = give_unicode_from_string(parsed,1); if (0x002E /* . */ != ch) return p_normal; if (2 == len) return p_up; /* ".." */ return p_normal; } /* ------------------------------------------------------------------------- */ #define URL_path_magic 0xEC04 struct url_path { unsigned short magic; /* URL_path_magic */ struct url_path_elem **elems; int elem_count; }; static struct url_path * alloc_url_path P_((void)); static struct url_path * alloc_url_path() { struct url_path *ret = safe_malloc (sizeof (*ret)); /* bzero is defined hdrs/defs.h */ bzero((void *)ret,sizeof (*ret)); ret->magic = URL_path_magic; ret->elems = NULL; ret->elem_count = 0; return ret; } struct url_path * raw_to_url_path(raw) struct string *raw; { int len = string_len(raw); int X = 0; int startpos = 0; int count = 1; struct url_path_elem **elems; int elem_count = 0; struct url_path *ret = NULL; uint16 ch = 0; for (X = 0; X < len; X++) { ch = give_unicode_from_string(raw,X); if (0x002F /* / */ == ch) count++; } DPRINT(Debug,12,(&Debug, "url_from_raw: count=%d raw=%S\n", count,raw)); elems = safe_malloc(count * sizeof (elems[0])); /* Special first element ... */ X = 0; if (len > 0) { ch = give_unicode_from_string(raw,X); if (0x002F /* / */ == ch) { elems[0] = alloc_url_path_elem(); elems[0]->elem = NULL; elems[0]->trailing_slash = 1; DPRINT(Debug,12,(&Debug, "raw_to_url_path: trailing slash -- root element\n")); elem_count = 1; X++; ch = 0; } } while ( X < len && elem_count < count) { struct string * elem = NULL; int L; startpos = X; for (; X < len; X++) { ch = give_unicode_from_string(raw,X); if (0x002F /* / */ == ch) break; } L = X - startpos; elem = clip_from_string(raw,&startpos,L); if (startpos != X) panic("URL PANIC",__FILE__,__LINE__,"raw_to_url_path", "Clipping Error",0); DPRINT(Debug,12,(&Debug, "raw_to_url_path: elem=%S\n",elem)); elems[elem_count] = alloc_url_path_elem(); elems[elem_count]->elem = element_from_raw(elem); if (0x002F /* / */ == ch) { elems[elem_count]->trailing_slash = 1; DPRINT(Debug,12,(&Debug, "raw_to_url_path: trailing slash\n")); X++; /* Skip / */ ch = 0; } elem_count++; free_string(&elem); } ret = alloc_url_path(); ret->elems = elems; ret->elem_count = elem_count; DPRINT(Debug,12,(&Debug, "raw_to_url_path: elem_count=%d\n",elem_count)); return ret; } int url_path_len(path) struct url_path *path; { if (URL_path_magic != path->magic) panic("URL PANIC",__FILE__,__LINE__,"url_path_len", "bad magic number",0); return path->elem_count; } CONST struct url_path_elem * get_url_path_element(path,idx) struct url_path *path; int idx; { if (URL_path_magic != path->magic) panic("URL PANIC",__FILE__,__LINE__,"get_url_path_element", "bad magic number",0); if (idx < 0 || idx >= path->elem_count) panic("URL PANIC",__FILE__,__LINE__,"get_url_path_element", "bad index",0); if (! path->elems[idx]) panic("URL PANIC",__FILE__,__LINE__,"get_url_path_element", "NULL element",0); return path->elems[idx]; } void free_url_path(path) struct url_path **path; { if (URL_path_magic != (*path)->magic) panic("URL PANIC",__FILE__,__LINE__,"free_url_path", "bad magic number",0); if ((*path)->elems) { int i; for (i = 0; i < (*path)->elem_count; i++) { if ((*path)->elems[i]) free_url_path_elem(& ((*path)->elems[i])); } free((*path)->elems); (*path)->elems = NULL; } (*path)->elem_count = 0; (*path)->magic = 0; /* Invalidate */ free(*path); *path = NULL; } struct url_path * join_url_path(parent,relative) struct url_path *parent; struct url_path *relative; { int count; struct url_path_elem **elems; int elem_count = 0; int i; struct url_path *ret = NULL; if (URL_path_magic != parent->magic) panic("URL PANIC",__FILE__,__LINE__,"join_url_path", "bad magic number (parent)",0); if (URL_path_magic != relative->magic) panic("URL PANIC",__FILE__,__LINE__,"join_url_path", "bad magic number (relative)",0); if (parent->elem_count < 1) panic("URL PANIC",__FILE__,__LINE__,"join_url_path", "Empty parent",0); count = parent->elem_count + relative->elem_count; elems = safe_malloc(count * sizeof (elems[0])); if (!parent->elems[0]->trailing_slash || parent->elems[0]->elem) panic("URL PANIC",__FILE__,__LINE__,"join_url_path", "Parent is not absolute",0); elems[elem_count++] = dup_url_path_elem(parent->elems[0]); for (i = 1; i < parent->elem_count; i++) { if (!parent->elems[i]->trailing_slash) break; elems[elem_count++] = dup_url_path_elem(parent->elems[i]); } if (elem_count < parent->elem_count-1) panic("URL PANIC",__FILE__,__LINE__,"join_url_path", "Bad parent path",0); for (i = 0; i < relative->elem_count; i++) { enum elem_class c = classify_url_path_elem(relative->elems[i]); if (p_error == c) goto failure; if (p_this == c) /* Skip "." element */ continue; if (p_up == c && elem_count > 1) { enum elem_class c1 = classify_url_path_elem(elems[elem_count]); if (p_error == c1) goto failure; if (p_normal == c1) { /* Remove one element */ free_url_path_elem(& elems[elem_count]); elem_count--; continue; } elems[elem_count++] = dup_url_path_elem(relative->elems[i]); } } ret = alloc_url_path(); ret->elems = elems; ret->elem_count = elem_count; DPRINT(Debug,12,(&Debug, "join_url_path: elem_count=%d\n",elem_count)); return ret; failure: for (i = 0; i < elem_count; i++) free_url_path_elem(& elems[i]); free(elems); return NULL; } struct url_path * dup_url_path(path) struct url_path *path; { struct url_path_elem **elems = NULL; int elem_count = 0; struct url_path *ret = NULL; if (URL_path_magic != path->magic) panic("URL PANIC",__FILE__,__LINE__,"dup_url_path", "bad magic number",0); if (path->elem_count > 0) { int i; elems = safe_malloc(path->elem_count * sizeof (elems[0])); for (i = 0; i < path->elem_count; i++) { elems[elem_count++] = dup_url_path_elem(path->elems[i]); } } ret = alloc_url_path(); ret->elems = elems; ret->elem_count = elem_count; DPRINT(Debug,12,(&Debug, "dup_url_path: elem_count=%d\n",elem_count)); return ret; } struct string * url_path_to_raw(url_path) struct url_path *url_path; { struct string * ret = NULL; charset_t ascii_ptr = MIME_name_to_charset("US-ASCII",0); int i; if (!ascii_ptr) panic("CHARSET PANIC",__FILE__,__LINE__,"url_path_to_raw", "US-ASCII not found",0); if (URL_path_magic != url_path->magic) panic("URL PANIC",__FILE__,__LINE__,"url_path_to_raw", "bad magic number",0); ret = new_string(ascii_ptr); for (i = 0; i < url_path->elem_count; i++) { /* On first element this is NULL */ if (url_path->elems[i]->elem) { CONST struct string * R = raw_from_element(url_path->elems[i]->elem); if (!R) { DPRINT(Debug,12,(&Debug, "url_path_to_raw: Failed to get url path element\n")); goto failure; } append_string(&ret,R); } /* This should be set on all elements except last */ if (url_path->elems[i]->trailing_slash) { add_ascii_to_string(ret,s2us("/")); } } return ret; failure: free_string(&ret); return NULL; } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */