#include "util.h" static bool parsley_exslt_registered = false; #define BUF 128 FILE* parsley_fopen(char* name, char* mode) { FILE* fo; if(!strcmp("-", name)) { if(!strcmp("w", mode)) { fo = stdout; } else { fo = stdin; } } else { fo = fopen(name, mode); } if(fo == NULL) { fprintf(stderr, "Cannot open file %s, error %d, %s\n", name, errno, strerror(errno)); exit(1); } return fo; } static int parsley_io_mode = 0; static char *parsley_user_agent_header = NULL; int parsley_io_get_mode() { return parsley_io_mode; } static xsltStylesheetPtr span_wrap_sheet = NULL; xmlDocPtr parsley_apply_span_wrap(xmlDocPtr doc) { if(span_wrap_sheet == NULL) { char * sheet = " \ \ \ \ \ \ \ \ \ "; xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); xmlDocPtr xml = xmlCtxtReadMemory(ctxt, sheet, strlen(sheet), NULL, NULL, 0); span_wrap_sheet = xsltParseStylesheetDoc(xml); } xsltTransformContextPtr ctxt = xsltNewTransformContext(span_wrap_sheet, doc); xmlSetGenericErrorFunc(ctxt, parsleyXsltError); xmlDocPtr out = xsltApplyStylesheetUser(span_wrap_sheet, doc, NULL, NULL, NULL, ctxt); xsltFreeTransformContext(ctxt); return out; } void _parsley_set_user_agent(char * agent) { if(parsley_user_agent_header != NULL) free(parsley_user_agent_header); if(agent == NULL) { parsley_user_agent_header = NULL; } else { asprintf(&parsley_user_agent_header, "User-Agent: %s\n", agent); } } static void * xmlUserAgentIOHTTPOpen(const char * file_name) { return (void *)(xmlNanoHTTPMethod(file_name, NULL, NULL, NULL, parsley_user_agent_header, 0)); } void parsley_io_set_mode(int mode) { if(mode == parsley_io_mode) return; parsley_io_mode = mode; xmlCleanupInputCallbacks(); if(parsley_io_mode & PARSLEY_OPTIONS_ALLOW_LOCAL) { xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen, xmlFileRead, xmlFileClose); #ifdef HAVE_ZLIB_H xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen, xmlGzfileRead, xmlGzfileClose); #endif /* HAVE_ZLIB_H */ } if(parsley_io_mode & PARSLEY_OPTIONS_ALLOW_NET) { #ifdef LIBXML_HTTP_ENABLED xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlUserAgentIOHTTPOpen, xmlIOHTTPRead, xmlIOHTTPClose); #endif /* LIBXML_HTTP_ENABLED */ #ifdef LIBXML_FTP_ENABLED xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, xmlIOFTPRead, xmlIOFTPClose); #endif /* LIBXML_FTP_ENABLED */ } } void printbuf_file_read(FILE *f, struct printbuf *buf) { char chars[BUF]; while(fgets(chars, BUF, f) != NULL){ sprintbuf(buf, "%s", chars); } } void registerEXSLT() { if(!parsley_exslt_registered) { exsltRegisterAll(); parsley_register_all(); init_xpath_alias(); exslt_org_regular_expressions_init(); parsley_exslt_registered = true; } } int parsley_key_flags(char* key) { char* ptr = key; char* last_alnum = key; char* last_paren = key; while(*ptr++ != '\0'){ if(isalnum(*ptr)) { last_alnum = ptr; } else if (*ptr == ')') { last_paren = ptr; } } ptr = (last_alnum > last_paren ? last_alnum : last_paren); int flags = 0; while(*ptr++ != '\0'){ switch(*ptr){ case '?': flags |= PARSLEY_OPTIONAL; break; case '!': flags |= PARSLEY_BANG; break; } } return flags; } char* parsley_key_tag(char* key) { char *tag = strdup(key); char *ptr = tag; while(*ptr++ != '\0'){ if(!isalnum(*ptr) && *ptr != '_' && *ptr != '-') { *ptr = 0; return tag; } } return tag; } pxpathPtr parsley_key_filter(char* key) { char *expr = strdup(key); char *ptr = expr; char *orig = expr; char *last_paren; int offset = 0; bool has_expr = false; while(*ptr++ != '\0'){ if(!has_expr) offset++; if(*ptr == '(') has_expr = true; if(*ptr == ')') last_paren = ptr; } if(!has_expr) return NULL; *last_paren = 0; // clip ")" expr += offset + 1; // clip "(" pxpathPtr out = strlen(expr) == 0 ? NULL : myparse(expr); free(orig); // free(expr); return out; } static xmlNodePtr _xmlLastElementChild(xmlNodePtr node) { xmlNodePtr child = node->children; xmlNodePtr elem = NULL; while(child != NULL) { if(child->type == XML_ELEMENT_NODE) elem = child; child = child->next; } return elem; } xmlNodePtr new_stylesheet_skeleton(char *incl) { struct printbuf *buf = printbuf_new(); sprintbuf(buf, "%s", "\n"); sprintbuf(buf, "%s", " \n"); sprintbuf(buf, "%s", "\n"); sprintbuf(buf, "%s", "\n"); sprintbuf(buf, "%s", ""); sprintbuf(buf, "%s", ""); sprintbuf(buf, "%s", ""); sprintbuf(buf, "%s", ""); sprintbuf(buf, "%s", ""); sprintbuf(buf, "%s", "\n"); sprintbuf(buf, "%s\n", incl); sprintbuf(buf, "%s\n", "\n"); sprintbuf(buf, "%s\n", "\n"); sprintbuf(buf, "%s\n", "\n"); sprintbuf(buf, "%s\n", "\n"); xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); xmlDocPtr doc = xmlCtxtReadMemory(ctxt, buf->buf, buf->size, "http://parselets.com/compiled", NULL, 3); xmlFreeParserCtxt(ctxt); printbuf_free(buf); xmlNodePtr node = xmlDocGetRootElement(doc); while(_xmlLastElementChild(node) != NULL) { node = _xmlLastElementChild(node); } return node; }