Ejemplo n.º 1
0
int Q_Sort(queue *q, int (*Comp)(const void *, const void *))
{
   int         i;
   void        *d;
   datanode    *dn;

   /* if already sorted free memory for tag array */

   if(q->sorted) {
      efree(queue_index);
      efree(queue_posn_index);
      q->sorted = False_;
   }

   /* Now allocate memory of array, array of pointers */

   queue_index = emalloc(q->size * sizeof(q->cursor->data));
   if(queue_index == NULL)
      return False_;

   queue_posn_index = emalloc(q->size * sizeof(q->cursor));
   if(queue_posn_index == NULL) {
      efree(queue_index);
      return False_;
   }

   /* Walk queue putting pointers into array */

   d = Q_Head(q);
   for(i=0; i < q->size; i++) {
      queue_index[i] = d;
      queue_posn_index[i] = q->cursor;
      d = Q_Next(q);
   }

   /* Now sort the index */

   QuickSort(queue_index, 0, q->size - 1, Comp);

   /* Rearrange the actual queue into correct order */

   dn = q->head;
   i = 0;
   while(dn != NULL) {
      dn->data = queue_index[i++];
      dn = dn->next;
   }

   /* Re-position to original element */

   if(d != NULL)
      Q_Find(q, d, Comp);
   else  Q_Head(q);

   q->sorted = True_;

   return True_;
}
Ejemplo n.º 2
0
/****f* xml_element/xml_elem_free
 * NAME
 *   xml_elem_free
 * SYNOPSIS
 *   void xml_elem_free(xml_element* root)
 * FUNCTION
 *   free an xml element and all of its child elements
 * INPUTS
 *   root - the root of an xml tree you would like to free
 * RESULT
 *   void
 * NOTES
 * SEE ALSO
 *   xml_elem_free_non_recurse ()
 *   xml_elem_new ()
 * SOURCE
 */
void xml_elem_free(xml_element* root) {
   if(root) {
      xml_element* kids = Q_Head(&root->children);
      while(kids) {
         xml_elem_free(kids);
         kids = Q_Next(&root->children);
      }
      xml_elem_free_non_recurse(root);
   }
}
Ejemplo n.º 3
0
/****f* xml_element/xml_elem_free_non_recurse
 * NAME
 *   xml_elem_free_non_recurse
 * SYNOPSIS
 *   void xml_elem_free_non_recurse(xml_element* root)
 * FUNCTION
 *   free a single xml element.  child elements will not be freed.
 * INPUTS
 *   root - the element to free
 * RESULT
 *   void
 * NOTES
 * SEE ALSO
 *   xml_elem_free ()
 *   xml_elem_new ()
 * SOURCE
 */
void xml_elem_free_non_recurse(xml_element* root) {
   if(root) {
      xml_element_attr* attrs = Q_Head(&root->attrs);
      while(attrs) {
         my_free(attrs->key);
         my_free(attrs->val);
         my_free(attrs);
         attrs = Q_Next(&root->attrs);
      }

      Q_Destroy(&root->children);
      Q_Destroy(&root->attrs);
      if(root->name) {
          free((char *)root->name);
          root->name = NULL;
      }
      simplestring_free(&root->text);
      my_free(root);
   }
}
Ejemplo n.º 4
0
int Q_Find(queue *q, void *data,
           int (*Comp)(const void *, const void *))
{
   void *d;

   if (q == NULL) {
	return False_;
   }

   d = Q_Head(q);
   do {
      if(Comp(d, data) == 0)
         return True_;
      d = Q_Next(q);
   } while(!Q_AtTail(q));

   if(Comp(d, data) == 0)
      return True_;

   return False_;
}
Ejemplo n.º 5
0
/****f* xml_element/xml_elem_free_non_recurse
 * NAME
 *   xml_elem_free_non_recurse
 * SYNOPSIS
 *   void xml_elem_free_non_recurse(xml_element* root)
 * FUNCTION
 *   free a single xml element.  child elements will not be freed.
 * INPUTS
 *   root - the element to free
 * RESULT
 *   void
 * NOTES
 * SEE ALSO
 *   xml_elem_free ()
 *   xml_elem_new ()
 * SOURCE
 */
void xml_elem_free_non_recurse(xml_element* root) {
   if(root) {
      xml_element_attr* attrs = Q_Head(&root->attrs);
      while(attrs) {
         my_free(attrs->key);
         my_free(attrs->val);
         my_free(attrs);
         attrs = Q_Next(&root->attrs);
      }

      Q_Destroy(&root->children);
      Q_Destroy(&root->attrs);
      // gcc-4.0 problem with:
      // my_free((char*)root->name);
      if(root->name) {
          char* p = (char*)root->name;
          my_free(p);
      }

      simplestring_free(&root->text);
      my_free(root);
   }
}
Ejemplo n.º 6
0
XMLRPC_VALUE xml_element_to_XMLRPC_REQUEST_worker(XMLRPC_REQUEST request, XMLRPC_VALUE parent_vector, XMLRPC_VALUE current_val, xml_element* el) {
   if (!current_val) {
      /* This should only be the case for the first element */
      current_val = XMLRPC_CreateValueEmpty();
   }

	if (el->name) {

      /* first, deal with the crazy/stupid fault format */
      if (!strcmp(el->name, ELEM_FAULT)) {
			xml_element* fault_value = (xml_element*)Q_Head(&el->children);
			XMLRPC_SetIsVector(current_val, xmlrpc_vector_struct);

         if(fault_value) {
            xml_element* fault_struct = (xml_element*)Q_Head(&fault_value->children);
            if(fault_struct) {
               xml_element* iter = (xml_element*)Q_Head(&fault_struct->children);

               while (iter) {
                  XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
                  xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
                  XMLRPC_AddValueToVector(current_val, xNextVal);
                  iter = (xml_element*)Q_Next(&fault_struct->children);
               }
            }
         }
      }
		else if (!strcmp(el->name, ELEM_DATA)	/* should be ELEM_ARRAY, but there is an extra level. weird */
			 || (!strcmp(el->name, ELEM_PARAMS) && 
				  (XMLRPC_RequestGetRequestType(request) == xmlrpc_request_call)) ) {		/* this "PARAMS" concept is silly.  dave?! */
         xml_element* iter = (xml_element*)Q_Head(&el->children);
         XMLRPC_SetIsVector(current_val, xmlrpc_vector_array);

         while (iter) {
            XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
            xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
            XMLRPC_AddValueToVector(current_val, xNextVal);
            iter = (xml_element*)Q_Next(&el->children);
         }
		}
		else if (!strcmp(el->name, ELEM_STRUCT)) {
         xml_element* iter = (xml_element*)Q_Head(&el->children);
         XMLRPC_SetIsVector(current_val, xmlrpc_vector_struct);

         while ( iter ) {
            XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
            xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
            XMLRPC_AddValueToVector(current_val, xNextVal);
            iter = (xml_element*)Q_Next(&el->children);
         }
		}
		else if (!strcmp(el->name, ELEM_STRING) || 
                 (!strcmp(el->name, ELEM_VALUE) && Q_Size(&el->children) == 0)) {
         XMLRPC_SetValueString(current_val, el->text.str, el->text.len);
		}
		else if (!strcmp(el->name, ELEM_NAME)) {
         XMLRPC_SetValueID_Case(current_val, el->text.str, 0, xmlrpc_case_exact);
		}
		else if (!strcmp(el->name, ELEM_INT) || !strcmp(el->name, ELEM_I4)) {
         XMLRPC_SetValueInt(current_val, atoi(el->text.str));
		}
		else if (!strcmp(el->name, ELEM_BOOLEAN)) {
         XMLRPC_SetValueBoolean(current_val, atoi(el->text.str));
		}
		else if (!strcmp(el->name, ELEM_DOUBLE)) {
         XMLRPC_SetValueDouble(current_val, atof(el->text.str));
		}
		else if (!strcmp(el->name, ELEM_DATETIME)) {
         XMLRPC_SetValueDateTime_ISO8601(current_val, el->text.str);
		}
		else if (!strcmp(el->name, ELEM_BASE64)) {
         struct buffer_st buf;
         base64_decode(&buf, el->text.str, el->text.len);
         XMLRPC_SetValueBase64(current_val, buf.data, buf.offset);
         buffer_delete(&buf);
		}
		else {
         xml_element* iter;

         if (!strcmp(el->name, ELEM_METHODCALL)) {
            if (request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
            }
			}
			else if (!strcmp(el->name, ELEM_METHODRESPONSE)) {
            if (request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_response);
            }
			}
			else if (!strcmp(el->name, ELEM_METHODNAME)) {
            if (request) {
               XMLRPC_RequestSetMethodName(request, el->text.str);
            }
         }

         iter = (xml_element*)Q_Head(&el->children);
         while ( iter ) {
            xml_element_to_XMLRPC_REQUEST_worker(request, parent_vector, 
                                                 current_val, iter);
            iter = (xml_element*)Q_Next(&el->children);
         }
      }
   }
   return current_val;
}
Ejemplo n.º 7
0
/****f* xml_element/xml_elem_parse_buf
 * NAME
 *   xml_elem_parse_buf
 * SYNOPSIS
 *   xml_element* xml_elem_parse_buf(const char* in_buf, int len, XML_ELEM_INPUT_OPTIONS options, XML_ELEM_ERROR error)
 * FUNCTION
 *   parse a buffer containing XML into an xml_element in-memory tree
 * INPUTS
 *   in_buf   - buffer containing XML document
 *   len      - length of buffer
 *   options  - input options. optional
 *   error    - error result data. optional. check if result is null.
 * RESULT
 *   void
 * NOTES
 *   The returned data must be free'd by caller
 * SEE ALSO
 *   xml_elem_serialize_to_string ()
 *   xml_elem_free ()
 * SOURCE
 */
xml_element* xml_elem_parse_buf(const char* in_buf, int len, XML_ELEM_INPUT_OPTIONS options, XML_ELEM_ERROR error)
{
   xml_element* xReturn = NULL;
   char buf[100] = "";
   static STRUCT_XML_ELEM_INPUT_OPTIONS default_opts = {encoding_utf_8};

   if(!options) {
      options = &default_opts;
   }

   if(in_buf) {
      XML_Parser parser;
      xml_elem_data mydata = {0};

      parser = XML_ParserCreate(NULL);

      mydata.root = xml_elem_new();
      mydata.current = mydata.root;
      mydata.input_options = options;
      mydata.needs_enc_conversion = options->encoding && strcmp(options->encoding, encoding_utf_8);

      XML_SetElementHandler(parser, (XML_StartElementHandler)_xmlrpc_startElement, (XML_EndElementHandler)_xmlrpc_endElement);
      XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler)_xmlrpc_charHandler);

      /* pass the xml_elem_data struct along */
      XML_SetUserData(parser, (void*)&mydata);

      if(!len) {
         len = strlen(in_buf);
      }

      /* parse the XML */
      if(XML_Parse(parser, in_buf, len, 1) == 0) {
         enum XML_Error err_code = XML_GetErrorCode(parser);
         int line_num = XML_GetCurrentLineNumber(parser);
         int col_num = XML_GetCurrentColumnNumber(parser);
         long byte_idx = XML_GetCurrentByteIndex(parser);
/*         int byte_total = XML_GetCurrentByteCount(parser); */
         const char * error_str = XML_ErrorString(err_code);
         if(byte_idx >= 0) {
             snprintf(buf, 
                      sizeof(buf),
                      "\n\tdata beginning %ld before byte index: %s\n",
                      byte_idx > 10  ? 10 : byte_idx,
                      in_buf + (byte_idx > 10 ? byte_idx - 10 : byte_idx));
         }
/*
         fprintf(stderr, "expat reports error code %i\n"
                "\tdescription: %s\n"
                "\tline: %i\n"
                "\tcolumn: %i\n"
                "\tbyte index: %ld\n"
                "\ttotal bytes: %i\n%s ",
                err_code, error_str, line_num, 
                col_num, byte_idx, byte_total, buf);
*/

          /* error condition */
          if(error) {
              error->parser_code = (long)err_code;
              error->line = line_num;
              error->column = col_num;
              error->byte_index = byte_idx;
              error->parser_error = error_str;
          }
      }
      else {
         xReturn = (xml_element*)Q_Head(&mydata.root->children);
         xReturn->parent = NULL;
      }

      XML_ParserFree(parser);


      xml_elem_free_non_recurse(mydata.root);
   }

   return xReturn;
}
Ejemplo n.º 8
0
static void xml_element_serialize(xml_element *el, int (*fptr)(void *data, const char *text, int size), void *data, XML_ELEM_OUTPUT_OPTIONS options, int depth)
{
   int i;
   static STRUCT_XML_ELEM_OUTPUT_OPTIONS default_opts = {xml_elem_pretty, xml_elem_markup_escaping | xml_elem_non_print_escaping, XML_DECL_ENCODING_DEFAULT};
   static char whitespace[] = "                                                                                               "
                              "                                                                                               "
                              "                                                                                               ";
   depth++;

   if(!el) {
      /* fprintf(stderr, "Nothing to write\n"); */
      return;
   }
   if(!options) {
      options = &default_opts;
   }

   /* print xml declaration if at root level */
   if(depth == 1) {
      xml_elem_writefunc(fptr, XML_DECL_START, data, XML_DECL_START_LEN);
      xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN);
      xml_elem_writefunc(fptr, XML_DECL_VERSION, data, XML_DECL_VERSION_LEN);
      if(options->encoding && *options->encoding) {
          xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN);
          xml_elem_writefunc(fptr, XML_DECL_ENCODING_ATTR, data, XML_DECL_ENCODING_ATTR_LEN);
          xml_elem_writefunc(fptr, EQUALS, data, EQUALS_LEN);
          xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);
          xml_elem_writefunc(fptr, options->encoding, data, 0);
          xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);
      }
      xml_elem_writefunc(fptr, XML_DECL_END, data, XML_DECL_END_LEN);
      if(options->verbosity != xml_elem_no_white_space) {
         xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN);
      }
   }

   if(options->verbosity == xml_elem_pretty && depth > 2) {
         xml_elem_writefunc(fptr, whitespace, data, depth - 2);
   }
   /* begin element */
   xml_elem_writefunc(fptr,START_TOKEN_BEGIN, data, START_TOKEN_BEGIN_LEN);
   if(el->name) {
      xml_elem_writefunc(fptr, el->name, data, 0);

      /* write attrs, if any */
      if(Q_Size(&el->attrs)) {
         xml_element_attr* iter = Q_Head(&el->attrs);
         while( iter ) {
            xml_elem_writefunc(fptr, WHITESPACE, data, WHITESPACE_LEN);
            xml_elem_writefunc(fptr, iter->key, data, 0);
            xml_elem_writefunc(fptr, EQUALS, data, EQUALS_LEN);
            xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);
            xml_elem_writefunc(fptr, iter->val, data, 0);
            xml_elem_writefunc(fptr, ATTR_DELIMITER, data, ATTR_DELIMITER_LEN);

            iter = Q_Next(&el->attrs);
         }
      }
   }
   else {
      xml_elem_writefunc(fptr, "None", data, 0);
   }
   /* if no text and no children, use abbreviated form, eg: <foo/> */
   if(!el->text.len && !Q_Size(&el->children)) {
       xml_elem_writefunc(fptr, EMPTY_START_TOKEN_END, data, EMPTY_START_TOKEN_END_LEN);
   }
   /* otherwise, print element contents */
   else {
       xml_elem_writefunc(fptr, START_TOKEN_END, data, START_TOKEN_END_LEN);

       /* print text, if any */
       if(el->text.len) {
          char* escaped_str = el->text.str;
          int buflen = el->text.len;

          if(options->escaping && options->escaping != xml_elem_cdata_escaping) {
             escaped_str = xml_elem_entity_escape(el->text.str, buflen, &buflen, options->escaping );
             if(!escaped_str) {
                escaped_str = el->text.str;
             }
          }

          if(options->escaping & xml_elem_cdata_escaping) {
             xml_elem_writefunc(fptr, CDATA_BEGIN, data, CDATA_BEGIN_LEN);
          }

          xml_elem_writefunc(fptr, escaped_str, data, buflen);

          if(escaped_str != el->text.str) {
             my_free(escaped_str);
          }

          if(options->escaping & xml_elem_cdata_escaping) {
             xml_elem_writefunc(fptr, CDATA_END, data, CDATA_END_LEN);
          }
       }
       /* no text, so print child elems */
       else {
          xml_element *kids = Q_Head(&el->children);
          i = 0;
          while( kids ) {
             if(i++ == 0) {
                if(options->verbosity != xml_elem_no_white_space) {
                   xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN);
                }
             }
             xml_element_serialize(kids, fptr, data, options, depth);
             kids = Q_Next(&el->children);
          }
          if(i) {
             if(options->verbosity == xml_elem_pretty && depth > 2) {
                   xml_elem_writefunc(fptr, whitespace, data, depth - 2);
             }
          }
       }

       xml_elem_writefunc(fptr, END_TOKEN_BEGIN, data, END_TOKEN_BEGIN_LEN);
       xml_elem_writefunc(fptr,el->name ? el->name : "None", data, 0);
       xml_elem_writefunc(fptr, END_TOKEN_END, data, END_TOKEN_END_LEN);
   }
   if(options->verbosity != xml_elem_no_white_space) {
      xml_elem_writefunc(fptr, NEWLINE, data, NEWLINE_LEN);
   }
}
Ejemplo n.º 9
0
XMLRPC_VALUE xml_element_to_DANDARPC_REQUEST_worker(XMLRPC_REQUEST request, XMLRPC_VALUE xCurrent, xml_element* el) {
   if(!xCurrent) {
      xCurrent = XMLRPC_CreateValueEmpty();
   }

   if(el->name) {
      const char* id = NULL;
      const char* type = NULL;
      xml_element_attr* attr_iter = Q_Head(&el->attrs);

      while(attr_iter) {
         if(!strcmp(attr_iter->key, ATTR_ID)) {
            id = attr_iter->val;
         }
         if(!strcmp(attr_iter->key, ATTR_TYPE)) {
            type = attr_iter->val;
         }
         attr_iter = Q_Next(&el->attrs);
      }

      if(id) {
         XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
      }

      if(!strcmp(el->name, ATTR_SCALAR)) {
         if(!type || !strcmp(type, ATTR_STRING)) {
            XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len);
         }
         else if(!strcmp(type, ATTR_INT)) {
            XMLRPC_SetValueInt(xCurrent, atoi(el->text.str));
         }
         else if(!strcmp(type, ATTR_BOOLEAN)) {
            XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str));
         }
         else if(!strcmp(type, ATTR_DOUBLE)) {
            XMLRPC_SetValueDouble(xCurrent, atof(el->text.str));
         }
         else if(!strcmp(type, ATTR_DATETIME)) {
            XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str);
         }
         else if(!strcmp(type, ATTR_BASE64)) {
            struct buffer_st buf;
            base64_decode_xmlrpc(&buf, el->text.str, el->text.len);
            XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset);
            buffer_delete(&buf);
         }
      }
      else if(!strcmp(el->name, ATTR_VECTOR)) {
         xml_element* iter = (xml_element*)Q_Head(&el->children);

         if(!type || !strcmp(type, ATTR_MIXED)) {
            XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
         }
         else if(!strcmp(type, ATTR_ARRAY)) {
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
         }
         else if(!strcmp(type, ATTR_STRUCT)) {
            XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct);
         }
         while( iter ) {
            XMLRPC_VALUE xNext = XMLRPC_CreateValueEmpty();
            xml_element_to_DANDARPC_REQUEST_worker(request, xNext, iter);
            XMLRPC_AddValueToVector(xCurrent, xNext);
            iter = (xml_element*)Q_Next(&el->children);
         }
      }
      else {
         xml_element* iter = (xml_element*)Q_Head(&el->children);
         while( iter ) {
            xml_element_to_DANDARPC_REQUEST_worker(request, xCurrent, iter);
            iter = (xml_element*)Q_Next(&el->children);
         }

         if(!strcmp(el->name, ELEM_METHODCALL)) {
            if(request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
            }
         }
         else if(!strcmp(el->name, ELEM_METHODRESPONSE)) {
            if(request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_response);
            }
         }
         else if(!strcmp(el->name, ELEM_METHODNAME)) {
            if(request) {
               XMLRPC_RequestSetMethodName(request, el->text.str);
            }
         }
      }
   }
   return xCurrent;
}
Ejemplo n.º 10
0
/* 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;
}
Ejemplo n.º 11
0
/* convert XMLRPC_REQUEST to soap xml dom. */
xml_element* SOAP_REQUEST_to_xml_element(XMLRPC_REQUEST request) {
	xml_element* root = xml_elem_new();

	/* safety first. */
	if (root) {
		xml_element* body = xml_elem_new();
		root->name = strdup("SOAP-ENV:Envelope");

		/* silly namespace stuff */
		Q_PushTail(&root->attrs, new_attr("xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"));
		Q_PushTail(&root->attrs, new_attr("xmlns:xsi", "http://www.w3.org/1999/XMLSchema-instance"));
		Q_PushTail(&root->attrs, new_attr("xmlns:xsd", "http://www.w3.org/1999/XMLSchema"));
		Q_PushTail(&root->attrs, new_attr("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"));
		Q_PushTail(&root->attrs, new_attr("xmlns:si", "http://soapinterop.org/xsd"));
		Q_PushTail(&root->attrs, new_attr("xmlns:ns6", "http://testuri.org"));
		Q_PushTail(&root->attrs, new_attr("SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"));

		/* Q_PushHead(&root->attrs, new_attr("xmlns:ks", "http://kitchen.sink.org/soap/everything/under/sun"));
		       JUST KIDDING!! :-)  ---->                ------------------------------------------------- */

		if (body) {
			/* go ahead and serialize first... */
			xml_element* el_serialized =  
			SOAP_to_xml_element_worker(request, 
												XMLRPC_RequestGetData(request));

			/* check for fault, in which case, there is no intermediate element */
			if (el_serialized && !strcmp(el_serialized->name, TOKEN_FAULT)) {
				Q_PushTail(&body->children, el_serialized);
			}
			/* usual case: not a fault. Add Response element in between. */
			else {
				xml_element* rpc = xml_elem_new();

				if (rpc) {
					const char* methodname = XMLRPC_RequestGetMethodName(request);
					XMLRPC_REQUEST_TYPE rtype = XMLRPC_RequestGetRequestType(request);

					/* if we are making a request, we want to use the methodname as is. */
					if (rtype == xmlrpc_request_call) {
						if (methodname) {
							rpc->name = strdup(methodname);
						}
					}
					/* if it's a response, we append "Response". Also, given xmlrpc-epi
					   API/architecture, it's likely that we don't have a methodname for
					   the response, so we have to check that. */
					else {
						char buf[128];
						snprintf(buf, sizeof(buf), "%s%s", 
									methodname ? methodname : "",
									"Response");

						rpc->name = strdup(buf);
					}

					/* add serialized data to method call/response.
					   add method call/response to body element */
					if (rpc->name) {
						if(el_serialized) {
							if(Q_Size(&el_serialized->children) && rtype == xmlrpc_request_call) {
								xml_element* iter = (xml_element*)Q_Head(&el_serialized->children);
								while(iter) {
									Q_PushTail(&rpc->children, iter);
									iter = (xml_element*)Q_Next(&el_serialized->children);
								}
								xml_elem_free_non_recurse(el_serialized);
							}
							else {
								Q_PushTail(&rpc->children, el_serialized);
							}
						}

						Q_PushTail(&body->children, rpc);
					}
					else {
						/* no method name?!
						   TODO: fault here...? */
					}
				}
			}
			body->name = strdup("SOAP-ENV:Body");
			Q_PushTail(&root->children, body);
		}
	}

	return root;
}
Ejemplo n.º 12
0
/* translates xml soap dom to native data structures. recursive. */
XMLRPC_VALUE xml_element_to_SOAP_REQUEST_worker(XMLRPC_REQUEST request, 
																XMLRPC_VALUE xParent,
																struct array_info* parent_array,
																XMLRPC_VALUE xCurrent, 
																xml_element* el, 
																int depth) {
	XMLRPC_REQUEST_TYPE rtype = xmlrpc_request_none;

	/* no current element on first call */
	if (!xCurrent) {
		xCurrent = XMLRPC_CreateValueEmpty();
	}

	/* increment recursion depth guage */
	depth ++;

	/* safety first. must have a valid element */
	if (el && el->name) {
		const char* id = NULL;
		const char* type = NULL, *arrayType=NULL, *actor = NULL;
		xml_element_attr* attr_iter = Q_Head(&el->attrs);
		int b_must_understand = 0;
		
		/* in soap, types may be specified in either element name -or- with xsi:type attribute. */
		if (is_soap_type(el->name)) {
			type = el->name;
		}
		/* if our parent node, by definition a vector, is not an array, then
		   our element name must be our key identifier. */
		else if (XMLRPC_GetVectorType(xParent) != xmlrpc_vector_array) {
			id = el->name;
			if(!strcmp(id, "item")) {
			}
		}

		/* iterate through element attributes, pick out useful stuff. */
		while (attr_iter) {
			/* element's type */
			if (!strcmp(attr_iter->key, TOKEN_TYPE)) {
				type = attr_iter->val;
			}
			/* array type */
			else if (!strcmp(attr_iter->key, TOKEN_ARRAY_TYPE)) {
				arrayType = attr_iter->val;
			}
			/* must understand, sometimes present in headers. */
			else if (!strcmp(attr_iter->key, TOKEN_MUSTUNDERSTAND)) {
				b_must_understand = strchr(attr_iter->val, '1') ? 1 : 0;
			}
			/* actor, used in conjuction with must understand. */
			else if (!strcmp(attr_iter->key, TOKEN_ACTOR)) {
				actor = attr_iter->val;
			}
			attr_iter = Q_Next(&el->attrs);
		}

		/* check if caller says we must understand something in a header. */
		if (b_must_understand) {
			/* is must understand actually indended for us?
			   BUG: spec says we should also determine if actor is our URL, but
			        we do not have that information. */
			if (!actor || !strcmp(actor, TOKEN_ACTOR_NEXT)) {
				/* TODO: implement callbacks or other mechanism for applications
				   to "understand" these headers. For now, we just bail if we
				   get a mustUnderstand header intended for us. */
				XMLRPC_RequestSetError(request, 
											  gen_soap_fault("SOAP-ENV:MustUnderstand",
																  "SOAP Must Understand Error",
																  "", ""));
				return xCurrent;
			}
		}

		/* set id (key) if one was found. */
		if (id) {
			XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
		}

		/* according to soap spec, 
		   depth 1 = Envelope, 2 = Header, Body & Fault, 3 = methodcall or response. */
		if (depth == 3) {
			const char* methodname = el->name;
			char* p = NULL;

			/* BUG: we determine request or response type using presence of "Response" in element name.
			   According to spec, this is only recommended, not required. Apparently, implementations
			   are supposed to know the type of action based on state, which strikes me as a bit lame.
			   Anyway, we don't have that state info, thus we use Response as a heuristic. */
			rtype =
#ifdef strcasestr
			strcasestr(el->name, "response") ? xmlrpc_request_response : xmlrpc_request_call;
#else
			strstr(el->name, "esponse") ? xmlrpc_request_response : xmlrpc_request_call;
#endif
			XMLRPC_RequestSetRequestType(request, rtype);

			/* Get methodname.  strip xml namespace crap. */
			p = strchr(el->name, ':');
			if (p) {
				methodname = p + 1;
			}
			if (rtype == xmlrpc_request_call) {
				XMLRPC_RequestSetMethodName(request, methodname);
			}
		}


		/* Next, we begin to convert actual values. if no children, then must be a scalar value. */
		if (!Q_Size(&el->children)) {
			if (!type && parent_array && parent_array->kids_type[0]) {
				type = parent_array->kids_type;
			}
			if (!type || !strcmp(type, TOKEN_STRING)) {
				XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len);
			}
			else if (!strcmp(type, TOKEN_INT)) {
				XMLRPC_SetValueInt(xCurrent, atoi(el->text.str));
			}
			else if (!strcmp(type, TOKEN_BOOLEAN)) {
				XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str));
			}
			else if (!strcmp(type, TOKEN_DOUBLE) ||
						!strcmp(type, TOKEN_FLOAT)) {
				XMLRPC_SetValueDouble(xCurrent, atof(el->text.str));
			}
			else if (!strcmp(type, TOKEN_NULL)) {
				/* already an empty val. do nothing. */
			}
			else if (!strcmp(type, TOKEN_DATETIME)) {
				XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str);
			}
			else if (!strcmp(type, TOKEN_BASE64)) {
				struct buffer_st buf;
				base64_decode_xmlrpc(&buf, el->text.str, el->text.len);
				XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset);
				buffer_delete(&buf);
			}
		}
		/* Element has children, thus a vector, or "compound type" in soap-speak. */
		else {
			struct array_info* ai = NULL;
			xml_element* iter = (xml_element*)Q_Head(&el->children);

			if (!type || !strcmp(type, TOKEN_STRUCT)) {
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct);
			}
			else if (!strcmp(type, TOKEN_ARRAY) || arrayType != NULL) {
				/* determine magic associated with soap array type.
				   this is passed down as we recurse, so our children have access to the info. */
				ai = parse_array_type_info(arrayType);	/* alloc'ed ai free'd below.*/
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
			}
			else {
				/* mixed is probably closest thing we have to compound type. */
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
			}
			/* Recurse, adding values as we go.  Check for error during recursion
			   and if found, bail.  this short-circuits us out of the recursion. */
			while ( iter && !XMLRPC_RequestGetError(request) ) {
				XMLRPC_VALUE xNext = NULL;
				/* top level elements don't actually represent values, so we just pass the
				   current value along until we are deep enough. */
				if ( depth <= 2 ||
					  (rtype == xmlrpc_request_response && depth <= 3) ) {
					xml_element_to_SOAP_REQUEST_worker(request, NULL, ai, xCurrent, iter, depth);
				}
				/* ready to do some actual de-serialization. create a new empty value and
				   pass that along to be init'd, then add it to our current vector. */
				else {
					xNext = XMLRPC_CreateValueEmpty();
					xml_element_to_SOAP_REQUEST_worker(request, xCurrent, ai, xNext, iter, depth);
					XMLRPC_AddValueToVector(xCurrent, xNext);
				}
				iter = (xml_element*)Q_Next(&el->children);
			}
			/* cleanup */
			if (ai) {
				free(ai);
			}
		}
	}
	return xCurrent;
}