PageRenderTime 507ms CodeModel.GetById 221ms app.highlight 20ms RepoModel.GetById 262ms app.codeStats 0ms

/util.c

http://github.com/fizx/parsley
C | 237 lines | 210 code | 26 blank | 1 comment | 43 complexity | 3cae780bc31d4c682a87913cbd970f05 MD5 | raw file
  1#include "util.h"
  2
  3static bool parsley_exslt_registered = false;
  4
  5#define BUF 128
  6
  7FILE* parsley_fopen(char* name, char* mode) {
  8	FILE* fo;
  9	if(!strcmp("-", name)) {
 10		if(!strcmp("w", mode)) {
 11			fo = stdout;
 12		} else {
 13			fo = stdin;
 14		}
 15	} else {
 16		fo = fopen(name, mode);
 17	}
 18	if(fo == NULL) {		
 19    fprintf(stderr, "Cannot open file %s, error %d, %s\n", name, errno, strerror(errno));
 20		exit(1);
 21	}
 22	return fo;	
 23}
 24
 25static int parsley_io_mode = 0;
 26static char *parsley_user_agent_header = NULL;
 27
 28int
 29parsley_io_get_mode() {
 30  return parsley_io_mode;
 31}
 32
 33static xsltStylesheetPtr span_wrap_sheet = NULL;
 34
 35xmlDocPtr 
 36parsley_apply_span_wrap(xmlDocPtr doc) {
 37  if(span_wrap_sheet == NULL) {
 38    char * sheet = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:sg=\"http://selectorgadget.com/\"> \
 39      <xsl:template match=\"text()[(following-sibling::* or preceding-sibling::*) and normalize-space(.) != '']\"> \
 40        <sg_wrap><xsl:value-of select=\".\" /></sg_wrap> \
 41      </xsl:template> \
 42    	<xsl:template match=\"@*|node()\"> \
 43    	  <xsl:copy> \
 44          <xsl:apply-templates select=\"@*|node()\"/> \
 45    	  </xsl:copy> \
 46    	</xsl:template> \
 47    </xsl:stylesheet>";
 48    
 49    xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
 50 		xmlDocPtr xml = xmlCtxtReadMemory(ctxt, sheet, strlen(sheet), NULL, NULL, 0);
 51    span_wrap_sheet = xsltParseStylesheetDoc(xml);
 52  }  
 53  xsltTransformContextPtr ctxt = xsltNewTransformContext(span_wrap_sheet, doc);
 54  xmlSetGenericErrorFunc(ctxt, parsleyXsltError);
 55  xmlDocPtr out = xsltApplyStylesheetUser(span_wrap_sheet, doc, NULL, NULL, NULL, ctxt);
 56  xsltFreeTransformContext(ctxt);
 57  return out;
 58}
 59
 60void
 61_parsley_set_user_agent(char * agent) {
 62  if(parsley_user_agent_header != NULL) free(parsley_user_agent_header);
 63  if(agent == NULL) {
 64    parsley_user_agent_header = NULL;
 65  } else {
 66    asprintf(&parsley_user_agent_header, "User-Agent: %s\n", agent);
 67  }
 68}
 69
 70static void *
 71xmlUserAgentIOHTTPOpen(const char * file_name) {
 72  return (void *)(xmlNanoHTTPMethod(file_name, NULL, NULL, NULL, parsley_user_agent_header, 0));
 73}
 74
 75void
 76parsley_io_set_mode(int mode) {
 77  if(mode == parsley_io_mode) return;
 78  parsley_io_mode = mode;
 79  
 80  xmlCleanupInputCallbacks();
 81  
 82  if(parsley_io_mode & PARSLEY_OPTIONS_ALLOW_LOCAL) {
 83  
 84    xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
 85  	                      xmlFileRead, xmlFileClose);
 86    #ifdef HAVE_ZLIB_H
 87        xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
 88    	                      xmlGzfileRead, xmlGzfileClose);
 89    #endif /* HAVE_ZLIB_H */
 90  }
 91  if(parsley_io_mode & PARSLEY_OPTIONS_ALLOW_NET) {
 92    #ifdef LIBXML_HTTP_ENABLED
 93        xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlUserAgentIOHTTPOpen,
 94    	                      xmlIOHTTPRead, xmlIOHTTPClose);
 95    #endif /* LIBXML_HTTP_ENABLED */
 96
 97    #ifdef LIBXML_FTP_ENABLED
 98        xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
 99    	                      xmlIOFTPRead, xmlIOFTPClose);
100    #endif /* LIBXML_FTP_ENABLED */
101  }
102}
103
104void
105printbuf_file_read(FILE *f, struct printbuf *buf) {
106  char chars[BUF];
107  while(fgets(chars, BUF, f) != NULL){
108    sprintbuf(buf, "%s", chars);
109  }
110}
111
112void registerEXSLT() {
113  if(!parsley_exslt_registered) {
114    exsltRegisterAll();
115		parsley_register_all();
116		init_xpath_alias();
117		exslt_org_regular_expressions_init();
118    parsley_exslt_registered = true;
119  }
120}
121
122int parsley_key_flags(char* key) {
123  char* ptr = key;
124  char* last_alnum = key;
125  char* last_paren = key;
126  while(*ptr++ != '\0'){
127    if(isalnum(*ptr)) {
128      last_alnum = ptr;
129    } else if (*ptr == ')') {
130      last_paren = ptr;
131    }
132  }
133  ptr = (last_alnum > last_paren ? last_alnum : last_paren);
134  int flags = 0;
135  while(*ptr++ != '\0'){
136    switch(*ptr){
137    case '?':
138      flags |= PARSLEY_OPTIONAL;
139      break;
140    case '!':
141      flags |= PARSLEY_BANG;
142      break;
143    }
144  }
145  return flags;
146}
147
148char* parsley_key_tag(char* key) {
149	char *tag = strdup(key);
150	char *ptr = tag;
151	while(*ptr++ != '\0'){
152		if(!isalnum(*ptr) && *ptr != '_' && *ptr != '-') {
153			*ptr = 0;
154			return tag;
155		}
156	}
157	return tag;
158}
159
160pxpathPtr parsley_key_filter(char* key) {
161	char *expr = strdup(key);
162	char *ptr = expr;
163	char *orig = expr;
164  char *last_paren;
165
166	int offset = 0;
167	bool has_expr = false;
168
169	while(*ptr++ != '\0'){
170		if(!has_expr)     offset++;
171		if(*ptr == '(')   has_expr = true;
172    if(*ptr == ')')   last_paren = ptr;
173	}
174	if(!has_expr) return NULL;
175  *last_paren = 0; // clip ")"
176	expr += offset + 1; // clip "("
177
178	pxpathPtr out = strlen(expr) == 0 ? NULL : myparse(expr);
179	free(orig);
180	// free(expr);
181	return out;
182}
183
184static xmlNodePtr
185_xmlLastElementChild(xmlNodePtr node) {
186  xmlNodePtr child = node->children;
187  xmlNodePtr elem = NULL;
188  while(child != NULL) {
189    if(child->type == XML_ELEMENT_NODE) elem = child;
190    child = child->next;
191  }
192  return elem;
193}
194
195xmlNodePtr new_stylesheet_skeleton(char *incl) {
196	struct printbuf *buf = printbuf_new();
197	sprintbuf(buf, "%s", "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"");
198	sprintbuf(buf, "%s", " xmlns:lib=\"http://parselets.com/stdlib\"");
199	sprintbuf(buf, "%s", " xmlns:parsley=\"http://parselets.com/json\"");
200	sprintbuf(buf, "%s", " xmlns:str=\"http://exslt.org/strings\"");
201	sprintbuf(buf, "%s", " xmlns:set=\"http://exslt.org/sets\"");
202	sprintbuf(buf, "%s", " xmlns:math=\"http://exslt.org/math\"");
203	sprintbuf(buf, "%s", " xmlns:func=\"http://exslt.org/functions\"");
204	sprintbuf(buf, "%s", " xmlns:user=\"http://parselets.com/usre\"");
205	sprintbuf(buf, "%s", " xmlns:dyn=\"http://exslt.org/dynamic\"");
206	sprintbuf(buf, "%s", " xmlns:date=\"http://exslt.org/dates-and-times\"");
207	sprintbuf(buf, "%s", " xmlns:exsl=\"http://exslt.org/common\"");
208	sprintbuf(buf, "%s", " xmlns:saxon=\"http://icl.com/saxon\"");
209	sprintbuf(buf, "%s", " xmlns:regexp=\"http://exslt.org/regular-expressions\"");
210	sprintbuf(buf, "%s", " xmlns:regex=\"http://exslt.org/regular-expressions\"");
211	sprintbuf(buf, "%s", " extension-element-prefixes=\"lib str math set func dyn exsl saxon user date regexp regex\"");
212	sprintbuf(buf, "%s", ">\n");
213  sprintbuf(buf, "%s", "<xsl:variable name=\"nbsp\">&#160;</xsl:variable>\n");
214	sprintbuf(buf, "%s", "<xsl:output method=\"xml\" indent=\"yes\"/>\n");
215	sprintbuf(buf, "%s", "<xsl:strip-space elements=\"*\"/>\n");
216	sprintbuf(buf, "%s", "<func:function name=\"lib:nl\"><xsl:param name=\"in\" select=\".\"/>");
217	sprintbuf(buf, "%s", "<xsl:variable name=\"out\"><xsl:apply-templates mode=\"innertext\" select=\"exsl:node-set($in)\"/></xsl:variable>");
218	sprintbuf(buf, "%s", "<func:result select=\"$out\" /></func:function>");
219	sprintbuf(buf, "%s", "<xsl:template match=\"text()\" mode=\"innertext\"><xsl:value-of select=\".\" /></xsl:template>");
220	sprintbuf(buf, "%s", "<xsl:template match=\"script|style\" mode=\"innertext\"/>");
221	sprintbuf(buf, "%s", "<xsl:template match=\"br|address|blockquote|center|dir|div|form|h1|h2|h3|h4|h5|h6|hr|menu|noframes|noscript|p|pre|li|td|th|p\" mode=\"innertext\"><xsl:apply-templates mode=\"innertext\" /><xsl:text>\n</xsl:text></xsl:template>");
222	sprintbuf(buf, "%s\n", incl);
223	sprintbuf(buf, "%s\n", "<xsl:template match=\"/\">\n");
224	sprintbuf(buf, "%s\n", "<parsley:root />\n");
225	sprintbuf(buf, "%s\n", "</xsl:template>\n");
226	sprintbuf(buf, "%s\n", "</xsl:stylesheet>\n");
227	xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
228	xmlDocPtr doc = xmlCtxtReadMemory(ctxt, buf->buf, buf->size, "http://parselets.com/compiled", NULL, 3);
229	xmlFreeParserCtxt(ctxt);
230	printbuf_free(buf);
231	
232	xmlNodePtr node = xmlDocGetRootElement(doc);
233	while(_xmlLastElementChild(node) != NULL) {
234		node = _xmlLastElementChild(node);
235	}
236	return node;
237}