Changeset b8d09c08c74bdbd3f495c71925483ecb98cb1a55

Show
Ignore:
Timestamp:
09/18/09 19:07:56 (5 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1253300876 +0000
git-parent:

[a1551f182d761cecc6451e8f8cc5b5f1b7d0d559]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1253300876 +0000
Message:

support for libxml2 querying

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/modules/lua_noit.c

    ra1551f1 rb8d09c0  
    3333#include "noit_defines.h" 
    3434 
    35 #include "noit_conf.h" 
    36 #include "noit_module.h" 
    37 #include "noit_check.h" 
    38 #include "noit_check_tools.h" 
    39 #include "utils/noit_log.h" 
    40 #include "utils/noit_str.h" 
    41 #include "eventer/eventer.h" 
    42 #include "lua_noit.h" 
    43  
    4435#include <assert.h> 
    4536#include <math.h> 
     
    5243#endif 
    5344#include <zlib.h> 
     45#include <libxml/parser.h> 
     46#include <libxml/xpath.h> 
     47#include <libxml/tree.h> 
     48 
     49#include "noit_conf.h" 
     50#include "noit_module.h" 
     51#include "noit_check.h" 
     52#include "noit_check_tools.h" 
     53#include "utils/noit_log.h" 
     54#include "utils/noit_str.h" 
     55#include "eventer/eventer.h" 
     56#include "lua_noit.h" 
    5457 
    5558#define DEFLATE_CHUNK_SIZE 32768 
     
    295298  assert(ci); 
    296299 
    297   if(mask & EVENTER_EXCEPTION) { 
    298     lua_pushnil(cl->L); 
    299     args = 1; 
    300     goto alldone; 
    301   } 
    302  
    303300  len = noit_lua_socket_do_read(e, &mask, cl, &args); 
    304301  if(len >= 0) { 
     
    312309    args = 1; 
    313310  } 
    314  alldone: 
    315311  eventer_remove_fd(e->fd); 
    316312  noit_lua_check_deregister_event(ci, e, 0); 
     
    951947  return 1; 
    952948} 
     949struct xpath_iter { 
     950  xmlXPathContextPtr ctxt; 
     951  xmlXPathObjectPtr pobj; 
     952  int cnt; 
     953  int idx; 
     954}; 
     955static int 
     956noit_lua_xpath_iter(lua_State *L) { 
     957  struct xpath_iter *xpi; 
     958  xpi = lua_touserdata(L, lua_upvalueindex(1)); 
     959  if(xpi->pobj) { 
     960    if(xpi->idx < xpi->cnt) { 
     961      xmlNodePtr node, *nodeptr; 
     962      node = xmlXPathNodeSetItem(xpi->pobj->nodesetval, xpi->idx); 
     963      xpi->idx++; 
     964      nodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(node)); 
     965      *nodeptr = node; 
     966      luaL_getmetatable(L, "noit.xmlnode"); 
     967      lua_setmetatable(L, -2); 
     968      return 1; 
     969    } 
     970  } 
     971  return 0; 
     972} 
     973static int 
     974noit_lua_xpath(lua_State *L) { 
     975  int n; 
     976  const char *xpathexpr; 
     977  xmlDocPtr *docptr, doc; 
     978  xmlNodePtr *nodeptr = NULL; 
     979  xmlXPathContextPtr ctxt; 
     980  struct xpath_iter *xpi; 
     981 
     982  n = lua_gettop(L); 
     983  /* the first arg is implicitly self (it's a method) */ 
     984  docptr = lua_touserdata(L, lua_upvalueindex(1)); 
     985  if(docptr != lua_touserdata(L, 1)) 
     986    luaL_error(L, "must be called as method"); 
     987  if(n < 2 || n > 3) luaL_error(L, "expects 1 or 2 arguments, got %d", n); 
     988  doc = *docptr; 
     989  xpathexpr = lua_tostring(L, 2); 
     990  if(!xpathexpr) luaL_error(L, "no xpath expression provided"); 
     991  ctxt = xmlXPathNewContext(doc); 
     992  if(n == 3) { 
     993    nodeptr = lua_touserdata(L, 3); 
     994    if(nodeptr) ctxt->node = *nodeptr; 
     995  } 
     996  if(!ctxt) luaL_error(L, "invalid xpath"); 
     997 
     998  xpi = (struct xpath_iter *)lua_newuserdata(L, sizeof(*xpi)); 
     999  xpi->ctxt = ctxt; 
     1000  xpi->pobj = xmlXPathEval((xmlChar *)xpathexpr, xpi->ctxt); 
     1001  if(!xpi->pobj || xpi->pobj->type != XPATH_NODESET) 
     1002    xpi->cnt = 0; 
     1003  else 
     1004    xpi->cnt = xmlXPathNodeSetGetLength(xpi->pobj->nodesetval); 
     1005  xpi->idx = 0; 
     1006  luaL_getmetatable(L, "noit.xpathiter"); 
     1007  lua_setmetatable(L, -2); 
     1008  lua_pushcclosure(L, noit_lua_xpath_iter, 1); 
     1009  return 1; 
     1010} 
     1011static int 
     1012noit_lua_xmlnode_attr(lua_State *L) { 
     1013  xmlNodePtr *nodeptr; 
     1014  /* the first arg is implicitly self (it's a method) */ 
     1015  nodeptr = lua_touserdata(L, lua_upvalueindex(1)); 
     1016  if(nodeptr != lua_touserdata(L, 1)) 
     1017    luaL_error(L, "must be called as method"); 
     1018  if(lua_gettop(L) == 2 && lua_isstring(L,2)) { 
     1019    xmlChar *v; 
     1020    const char *attr = lua_tostring(L,2); 
     1021    v = xmlGetProp(*nodeptr, (xmlChar *)attr); 
     1022    if(v) { 
     1023      lua_pushstring(L, (const char *)v); 
     1024      xmlFree(v); 
     1025    } 
     1026    else lua_pushnil(L); 
     1027    return 1; 
     1028  } 
     1029  luaL_error(L,"must be called with no arguments"); 
     1030  return 0; 
     1031} 
     1032static int 
     1033noit_lua_xmlnode_contents(lua_State *L) { 
     1034  xmlNodePtr *nodeptr; 
     1035  /* the first arg is implicitly self (it's a method) */ 
     1036  nodeptr = lua_touserdata(L, lua_upvalueindex(1)); 
     1037  if(nodeptr != lua_touserdata(L, 1)) 
     1038    luaL_error(L, "must be called as method"); 
     1039  if(lua_gettop(L) == 1) { 
     1040    xmlChar *v; 
     1041    v = xmlNodeGetContent(*nodeptr); 
     1042    if(v) { 
     1043      lua_pushstring(L, (const char *)v); 
     1044      xmlFree(v); 
     1045    } 
     1046    else lua_pushnil(L); 
     1047    return 1; 
     1048  } 
     1049  luaL_error(L,"must be called with no arguments"); 
     1050  return 0; 
     1051} 
     1052static int 
     1053noit_lua_xmlnode_next(lua_State *L) { 
     1054  xmlNodePtr *nodeptr; 
     1055  nodeptr = lua_touserdata(L, lua_upvalueindex(1)); 
     1056  if(*nodeptr) { 
     1057    xmlNodePtr *newnodeptr; 
     1058    newnodeptr = (xmlNodePtr *)lua_newuserdata(L, sizeof(*nodeptr)); 
     1059    *newnodeptr = *nodeptr; 
     1060    luaL_getmetatable(L, "noit.xmlnode"); 
     1061    lua_setmetatable(L, -2); 
     1062    *nodeptr = (*nodeptr)->next; 
     1063    return 1; 
     1064  } 
     1065  return 0; 
     1066} 
     1067static int 
     1068noit_lua_xmlnode_children(lua_State *L) { 
     1069  xmlNodePtr *nodeptr, node, cnode; 
     1070  /* the first arg is implicitly self (it's a method) */ 
     1071  nodeptr = lua_touserdata(L, lua_upvalueindex(1)); 
     1072  if(nodeptr != lua_touserdata(L, 1)) 
     1073    luaL_error(L, "must be called as method"); 
     1074  node = *nodeptr; 
     1075  cnode = node->children; 
     1076  nodeptr = lua_newuserdata(L, sizeof(cnode)); 
     1077  *nodeptr = cnode; 
     1078  luaL_getmetatable(L, "noit.xmlnode"); 
     1079  lua_setmetatable(L, -2); 
     1080  lua_pushcclosure(L, noit_lua_xmlnode_next, 1); 
     1081  return 1; 
     1082} 
     1083static int 
     1084noit_lua_xpathiter_gc(lua_State *L) { 
     1085  struct xpath_iter *xpi; 
     1086  xpi = lua_touserdata(L, 1); 
     1087  xmlXPathFreeContext(xpi->ctxt); 
     1088  if(xpi->pobj) xmlXPathFreeObject(xpi->pobj); 
     1089  return 0; 
     1090} 
     1091static int 
     1092noit_xmlnode_index_func(lua_State *L) { 
     1093  int n; 
     1094  const char *k; 
     1095  xmlNodePtr *udata, obj; 
     1096  n = lua_gettop(L); /* number of arguments */ 
     1097  assert(n == 2); 
     1098  if(!luaL_checkudata(L, 1, "noit.xmlnode")) { 
     1099    luaL_error(L, "metatable error, arg1 not a noit.xmlnode!"); 
     1100  } 
     1101  udata = lua_touserdata(L, 1); 
     1102  obj = *udata; 
     1103  if(!lua_isstring(L, 2)) { 
     1104    luaL_error(L, "metatable error, arg2 not a string!"); 
     1105  } 
     1106  k = lua_tostring(L, 2); 
     1107  switch(*k) { 
     1108    case 'a': 
     1109      if(!strcmp(k,"attr") || 
     1110         !strcmp(k,"attribute")) { 
     1111        lua_pushlightuserdata(L, udata); 
     1112        lua_pushcclosure(L, noit_lua_xmlnode_attr, 1); 
     1113        return 1; 
     1114      } 
     1115      break; 
     1116    case 'c': 
     1117      if(!strcmp(k,"children")) { 
     1118        lua_pushlightuserdata(L, udata); 
     1119        lua_pushcclosure(L, noit_lua_xmlnode_children, 1); 
     1120        return 1; 
     1121      } 
     1122      if(!strcmp(k,"contents")) { 
     1123        lua_pushlightuserdata(L, udata); 
     1124        lua_pushcclosure(L, noit_lua_xmlnode_contents, 1); 
     1125        return 1; 
     1126      } 
     1127      break; 
     1128    default: 
     1129      break; 
     1130  } 
     1131  luaL_error(L, "noit.xmlnode no such element: %s", k); 
     1132  return 0; 
     1133} 
     1134static int 
     1135nl_parsexml(lua_State *L) { 
     1136  xmlDocPtr *docptr, doc; 
     1137  const char *in; 
     1138  size_t inlen; 
     1139 
     1140  if(lua_gettop(L) != 1) luaL_error(L, "parsexml requires one argument");  
     1141 
     1142  in = lua_tolstring(L, 1, &inlen); 
     1143  doc = xmlParseMemory(in, inlen); 
     1144  if(!doc) { 
     1145    lua_pushnil(L); 
     1146    return 1; 
     1147  } 
     1148 
     1149  docptr = (xmlDocPtr *)lua_newuserdata(L, sizeof(doc));  
     1150  *docptr = doc; 
     1151  luaL_getmetatable(L, "noit.xmldoc"); 
     1152  lua_setmetatable(L, -2); 
     1153  return 1; 
     1154} 
     1155static int 
     1156noit_lua_xmldoc_gc(lua_State *L) { 
     1157  xmlDocPtr *holder; 
     1158  holder = (xmlDocPtr *)lua_touserdata(L,1); 
     1159  xmlFreeDoc(*holder); 
     1160  return 0; 
     1161} 
     1162static int 
     1163noit_xmldoc_index_func(lua_State *L) { 
     1164  int n; 
     1165  const char *k; 
     1166  xmlDocPtr *udata, obj; 
     1167  n = lua_gettop(L); /* number of arguments */ 
     1168  assert(n == 2); 
     1169  if(!luaL_checkudata(L, 1, "noit.xmldoc")) { 
     1170    luaL_error(L, "metatable error, arg1 not a noit.xmldoc!"); 
     1171  } 
     1172  udata = lua_touserdata(L, 1); 
     1173  obj = *udata; 
     1174  if(!lua_isstring(L, 2)) { 
     1175    luaL_error(L, "metatable error, arg2 not a string!"); 
     1176  } 
     1177  k = lua_tostring(L, 2); 
     1178  switch(*k) { 
     1179    case 'x': 
     1180     if(!strcmp(k, "xpath")) { 
     1181       lua_pushlightuserdata(L, udata); 
     1182       lua_pushcclosure(L, noit_lua_xpath, 1); 
     1183       return 1; 
     1184     } 
     1185     break; 
     1186    default: 
     1187     break; 
     1188  } 
     1189  luaL_error(L, "noit.xmldoc no such element: %s", k); 
     1190  return 0; 
     1191} 
    9531192static const luaL_Reg noitlib[] = { 
    9541193  { "sleep", nl_sleep }, 
     
    9641203  { "conf_get_boolean", nl_conf_get_boolean }, 
    9651204  { "conf_get_number", nl_conf_get_float }, 
     1205  { "parsexml", nl_parsexml }, 
    9661206  { NULL, NULL } 
    9671207}; 
     
    9821222  luaL_newmetatable(L, "noit.pcre"); 
    9831223  lua_pushcfunction(L, noit_lua_pcre_gc); 
     1224  lua_setfield(L, -2, "__gc"); 
     1225 
     1226  luaL_newmetatable(L, "noit.xmldoc"); 
     1227  lua_pushcfunction(L, noit_lua_xmldoc_gc); 
     1228  lua_setfield(L, -2, "__gc"); 
     1229  luaL_newmetatable(L, "noit.xmldoc"); 
     1230  lua_pushcclosure(L, noit_xmldoc_index_func, 0); 
     1231  lua_setfield(L, -2, "__index"); 
     1232 
     1233  luaL_newmetatable(L, "noit.xmlnode"); 
     1234  lua_pushcclosure(L, noit_xmlnode_index_func, 0); 
     1235  lua_setfield(L, -2, "__index"); 
     1236 
     1237  luaL_newmetatable(L, "noit.xpathiter"); 
     1238  lua_pushcfunction(L, noit_lua_xpathiter_gc); 
    9841239  lua_setfield(L, -2, "__gc"); 
    9851240