⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlrpc_introspection.c

📁 PHP v6.0 For Linux 运行环境:Win9X/ WinME/ WinNT/ Win2K/ WinXP
💻 C
📖 第 1 页 / 共 2 页
字号:
   return xParam;}/* convert an xml tree conforming to spec <url tbd> to  XMLRPC_VALUE * suitable for use with XMLRPC_ServerAddIntrospectionData */XMLRPC_VALUE xml_element_to_method_description(xml_element* el, XMLRPC_ERROR err) {   XMLRPC_VALUE xReturn = NULL;   if(el->name) {      const char* name = NULL;      const char* type = NULL;      const char* basetype = NULL;      const char* desc = NULL;      const char* def = NULL;      int optional = 0;      xml_element_attr* attr_iter = Q_Head(&el->attrs);      /* grab element attributes up front to save redundant while loops */      while(attr_iter) {         if(!strcmp(attr_iter->key, "name")) {            name = attr_iter->val;         }         else if(!strcmp(attr_iter->key, "type")) {            type = attr_iter->val;         }         else if(!strcmp(attr_iter->key, "basetype")) {            basetype = attr_iter->val;         }         else if(!strcmp(attr_iter->key, "desc")) {            desc = attr_iter->val;         }         else if(!strcmp(attr_iter->key, "optional")) {            if(attr_iter->val && !strcmp(attr_iter->val, "yes")) {               optional = 1;            }         }         else if(!strcmp(attr_iter->key, "default")) {            def = attr_iter->val;         }         attr_iter = Q_Next(&el->attrs);      }      /* value and typeDescription behave about the same */      if(!strcmp(el->name, "value") || !strcmp(el->name, "typeDescription")) {         XMLRPC_VALUE xSubList = NULL;         const char* ptype = !strcmp(el->name, "value") ? type : basetype;         if(ptype) {            if(Q_Size(&el->children) &&               (!strcmp(ptype, "array") || !strcmp(ptype, "struct") || !strcmp(ptype, "mixed"))) {               xSubList = XMLRPC_CreateVector("member", xmlrpc_vector_array);               if(xSubList) {                  xml_element* elem_iter = Q_Head(&el->children);                  while(elem_iter) {                     XMLRPC_AddValueToVector(xSubList,                                              xml_element_to_method_description(elem_iter, err));                     elem_iter = Q_Next(&el->children);                  }               }            }            xReturn = describeValue_worker(ptype, name, (desc ? desc : (xSubList ? NULL : el->text.str)), optional, def, xSubList);         }      }      /* these three kids are about equivalent */      else if(!strcmp(el->name, "params") ||               !strcmp(el->name, "returns") ||               !strcmp(el->name, "signature")) {         if(Q_Size(&el->children)) {            xml_element* elem_iter = Q_Head(&el->children);            xReturn = XMLRPC_CreateVector(!strcmp(el->name, "signature") ? NULL : el->name, xmlrpc_vector_struct);            while(elem_iter) {               XMLRPC_AddValueToVector(xReturn,                                        xml_element_to_method_description(elem_iter, err));               elem_iter = Q_Next(&el->children);            }         }      }      else if(!strcmp(el->name, "methodDescription")) {         xml_element* elem_iter = Q_Head(&el->children);         xReturn = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);         XMLRPC_VectorAppendString(xReturn, xi_token_name, name, 0);         while(elem_iter) {            XMLRPC_AddValueToVector(xReturn,                                     xml_element_to_method_description(elem_iter, err));            elem_iter = Q_Next(&el->children);         }      }      /* items are slightly special */      else if(!strcmp(el->name, "item")) {         xReturn = XMLRPC_CreateValueString(name, el->text.str, el->text.len);      }      /* sure.  we'll let any ol element with children through */      else if(Q_Size(&el->children)) {         xml_element* elem_iter = Q_Head(&el->children);         xReturn = XMLRPC_CreateVector(el->name, xmlrpc_vector_mixed);         while(elem_iter) {            XMLRPC_AddValueToVector(xReturn,                                     xml_element_to_method_description(elem_iter, err));            elem_iter = Q_Next(&el->children);         }      }      /* or anything at all really, so long as its got some text.        * no reason being all snotty about a spec, right?        */      else if(el->name && el->text.len) {         xReturn = XMLRPC_CreateValueString(el->name, el->text.str, el->text.len);      }   }   return xReturn;}/*-***************************** End Introspection Utilities *******************************//*-******************* Introspection API *********************//****f* VALUE/XMLRPC_IntrospectionCreateDescription * NAME *   XMLRPC_IntrospectionCreateDescription * SYNOPSIS *   XMLRPC_VALUE XMLRPC_IntrospectionCreateDescription(const char* xml, XMLRPC_ERROR err) * FUNCTION *   converts raw xml describing types and methods into an *   XMLRPC_VALUE suitable for use with XMLRPC_ServerAddIntrospectionData() * INPUTS *   xml - xml data conforming to introspection spec at <url tbd> *   err - optional pointer to error struct. filled in if error occurs and not NULL. * RESULT *   XMLRPC_VALUE - newly created value, or NULL if fatal error. * BUGS *   Currently does little or no validation of xml. *   Only parse errors are currently reported in err, not structural errors. * SEE ALSO *   XMLRPC_ServerAddIntrospectionData () * SOURCE */XMLRPC_VALUE XMLRPC_IntrospectionCreateDescription(const char* xml, XMLRPC_ERROR err) {   XMLRPC_VALUE xReturn = NULL;   xml_element* root = xml_elem_parse_buf(xml, 0, 0, err ? &err->xml_elem_error : NULL);   if(root) {      xReturn = xml_element_to_method_description(root, err);      xml_elem_free(root);   }   return xReturn;}/*******//****f* SERVER/XMLRPC_ServerAddIntrospectionData * NAME *   XMLRPC_ServerAddIntrospectionData * SYNOPSIS *   int XMLRPC_ServerAddIntrospectionData(XMLRPC_SERVER server, XMLRPC_VALUE desc) * FUNCTION *   updates server with additional introspection data * INPUTS *   server - target server *   desc - introspection data, should be a struct generated by  *          XMLRPC_IntrospectionCreateDescription () * RESULT *   int - 1 if success, else 0 * NOTES *  - function will fail if neither typeList nor methodList key is present in struct. *  - if method or type already exists, it will be replaced. *  - desc is never freed by the server.  caller is responsible for cleanup. * BUGS *   - horribly slow lookups. prime candidate for hash improvements. *   - uglier and more complex than I like to see for API functions. * SEE ALSO *   XMLRPC_ServerAddIntrospectionData () *   XMLRPC_ServerRegisterIntrospectionCallback () *   XMLRPC_CleanupValue () * SOURCE */int XMLRPC_ServerAddIntrospectionData(XMLRPC_SERVER server, XMLRPC_VALUE desc) {   int bSuccess = 0;   if(server && desc) {      XMLRPC_VALUE xNewTypes = XMLRPC_VectorGetValueWithID(desc, "typeList");      XMLRPC_VALUE xNewMethods = XMLRPC_VectorGetValueWithID(desc, "methodList");      XMLRPC_VALUE xServerTypes = XMLRPC_VectorGetValueWithID(server->xIntrospection, "typeList");      if(xNewMethods) {         XMLRPC_VALUE xMethod = XMLRPC_VectorRewind(xNewMethods);         while(xMethod) {            const char* name = XMLRPC_VectorGetStringWithID(xMethod, xi_token_name);            server_method* sm = find_method(server, name);            if(sm) {               if(sm->desc) {                  XMLRPC_CleanupValue(sm->desc);               }               sm->desc = XMLRPC_CopyValue(xMethod);               bSuccess = 1;            }            xMethod = XMLRPC_VectorNext(xNewMethods);         }      }      if(xNewTypes) {         if(!xServerTypes) {            if(!server->xIntrospection) {               server->xIntrospection = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);            }            XMLRPC_AddValueToVector(server->xIntrospection, xNewTypes);            bSuccess = 1;         }         else {            XMLRPC_VALUE xIter = XMLRPC_VectorRewind(xNewTypes);            while(xIter) {               /* get rid of old values */               XMLRPC_VALUE xPrev = find_named_value(xServerTypes, XMLRPC_VectorGetStringWithID(xIter, xi_token_name));               if(xPrev) {                  XMLRPC_VectorRemoveValue(xServerTypes, xPrev);               }               XMLRPC_AddValueToVector(xServerTypes, xIter);               bSuccess = 1;               xIter = XMLRPC_VectorNext(xNewTypes);            }         }      }   }   return bSuccess;}/*******//****f* SERVER/XMLRPC_ServerRegisterIntrospectionCallback * NAME *   XMLRPC_ServerRegisterIntrospectionCallback * SYNOPSIS *   int XMLRPC_ServerRegisterIntrospectionCallback(XMLRPC_SERVER server, XMLRPC_IntrospectionCallback cb) * FUNCTION *   registers a callback for lazy generation of introspection data * INPUTS *   server - target server *   cb - callback that will generate introspection data * RESULT *   int - 1 if success, else 0 * NOTES *   parsing xml and generating introspection data is fairly expensive, thus a *   server may wish to wait until this data is actually requested before generating *   it. Any number of callbacks may be registered at any time.  A given callback *   will only ever be called once, the first time an introspection request is *   processed after the time of callback registration. * SEE ALSO *   XMLRPC_ServerAddIntrospectionData () *   XMLRPC_IntrospectionCreateDescription () * SOURCE */int XMLRPC_ServerRegisterIntrospectionCallback(XMLRPC_SERVER server, XMLRPC_IntrospectionCallback cb) {   int bSuccess = 0;   if(server && cb) {      doc_method* dm = calloc(1, sizeof(doc_method));            if(dm) {         dm->method = cb;         dm->b_called = 0;         if(Q_PushTail(&server->docslist, dm)) {            bSuccess = 1;         }         else {            my_free(dm);         }      }   }   return 0;}/*******//*-*********************** End Introspection API *************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -