You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2521 lines
77 KiB

21 years ago
21 years ago
21 years ago
23 years ago
21 years ago
23 years ago
21 years ago
23 years ago
23 years ago
21 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2006 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Brad Lafountain <rodif_bl@yahoo.com> |
  16. | Shane Caraveo <shane@caraveo.com> |
  17. | Dmitry Stogov <dmitry@zend.com> |
  18. +----------------------------------------------------------------------+
  19. */
  20. /* $Id$ */
  21. #include "php_soap.h"
  22. #include "libxml/uri.h"
  23. static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpleType, sdlTypePtr cur_type);
  24. static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type);
  25. static int schema_list(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr listType, sdlTypePtr cur_type);
  26. static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTypePtr cur_type);
  27. static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompType, sdlTypePtr cur_type);
  28. static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType);
  29. static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type);
  30. static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type);
  31. static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type);
  32. static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model);
  33. static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model);
  34. static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model);
  35. static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTypePtr cur_type, sdlContentModelPtr model);
  36. static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model);
  37. static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model);
  38. static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx);
  39. static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx);
  40. static int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr);
  41. static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr);
  42. static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type);
  43. static encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlChar *ns, const xmlChar *type)
  44. {
  45. smart_str nscat = {0};
  46. encodePtr enc, *enc_ptr;
  47. if (sdl->encoders == NULL) {
  48. sdl->encoders = emalloc(sizeof(HashTable));
  49. zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
  50. }
  51. smart_str_appends(&nscat, (char*)ns);
  52. smart_str_appendc(&nscat, ':');
  53. smart_str_appends(&nscat, (char*)type);
  54. smart_str_0(&nscat);
  55. if (zend_hash_find(sdl->encoders, nscat.c, nscat.len + 1, (void**)&enc_ptr) == SUCCESS) {
  56. enc = *enc_ptr;
  57. if (enc->details.ns) {
  58. efree(enc->details.ns);
  59. }
  60. if (enc->details.type_str) {
  61. efree(enc->details.type_str);
  62. }
  63. } else {
  64. enc_ptr = NULL;
  65. enc = emalloc(sizeof(encode));
  66. }
  67. memset(enc, 0, sizeof(encode));
  68. enc->details.ns = estrdup((char*)ns);
  69. enc->details.type_str = estrdup((char*)type);
  70. enc->details.sdl_type = cur_type;
  71. enc->to_xml = sdl_guess_convert_xml;
  72. enc->to_zval = sdl_guess_convert_zval;
  73. if (enc_ptr == NULL) {
  74. zend_hash_update(sdl->encoders, nscat.c, nscat.len + 1, &enc, sizeof(encodePtr), NULL);
  75. }
  76. smart_str_free(&nscat);
  77. return enc;
  78. }
  79. static encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlChar *ns, const xmlChar *type)
  80. {
  81. encodePtr enc = get_encoder(sdl, (char*)ns, (char*)type);
  82. if (enc == NULL) {
  83. enc = create_encoder(sdl, cur_type, ns, type);
  84. }
  85. return enc;
  86. }
  87. static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlAttrPtr tns, int import TSRMLS_DC) {
  88. if (location != NULL &&
  89. !zend_hash_exists(&ctx->docs, (char*)location, xmlStrlen(location)+1)) {
  90. xmlDocPtr doc;
  91. xmlNodePtr schema;
  92. xmlAttrPtr new_tns;
  93. doc = soap_xmlParseFile((char*)location TSRMLS_CC);
  94. if (doc == NULL) {
  95. soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location);
  96. }
  97. schema = get_node(doc->children, "schema");
  98. if (schema == NULL) {
  99. xmlFreeDoc(doc);
  100. soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location);
  101. }
  102. new_tns = get_attribute(schema->properties, "targetNamespace");
  103. if (import) {
  104. if (ns != NULL && (new_tns == NULL || xmlStrcmp(ns->children->content, new_tns->children->content) != 0)) {
  105. xmlFreeDoc(doc);
  106. soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, ns->children->content);
  107. }
  108. if (ns == NULL && new_tns != NULL) {
  109. xmlFreeDoc(doc);
  110. soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, new_tns->children->content);
  111. }
  112. } else {
  113. new_tns = get_attribute(schema->properties, "targetNamespace");
  114. if (new_tns == NULL) {
  115. if (tns != NULL) {
  116. xmlSetProp(schema, BAD_CAST("targetNamespace"), tns->children->content);
  117. }
  118. } else if (tns != NULL && xmlStrcmp(tns->children->content, new_tns->children->content) != 0) {
  119. xmlFreeDoc(doc);
  120. soap_error1(E_ERROR, "Parsing Schema: can't include schema from '%s', different 'targetNamespace'", location);
  121. }
  122. }
  123. zend_hash_add(&ctx->docs, (char*)location, xmlStrlen(location)+1, (void**)&doc, sizeof(xmlDocPtr), NULL);
  124. load_schema(ctx, schema TSRMLS_CC);
  125. }
  126. }
  127. /*
  128. 2.6.1 xsi:type
  129. 2.6.2 xsi:nil
  130. 2.6.3 xsi:schemaLocation, xsi:noNamespaceSchemaLocation
  131. */
  132. /*
  133. <schema
  134. attributeFormDefault = (qualified | unqualified) : unqualified
  135. blockDefault = (#all | List of (extension | restriction | substitution)) : ''
  136. elementFormDefault = (qualified | unqualified) : unqualified
  137. finalDefault = (#all | List of (extension | restriction)) : ''
  138. id = ID
  139. targetNamespace = anyURI
  140. version = token
  141. xml:lang = language
  142. {any attributes with non-schema namespace . . .}>
  143. Content: ((include | import | redefine | annotation)*, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*)
  144. </schema>
  145. */
  146. int load_schema(sdlCtx *ctx, xmlNodePtr schema TSRMLS_DC)
  147. {
  148. xmlNodePtr trav;
  149. xmlAttrPtr tns;
  150. if (!ctx->sdl->types) {
  151. ctx->sdl->types = emalloc(sizeof(HashTable));
  152. zend_hash_init(ctx->sdl->types, 0, NULL, delete_type, 0);
  153. }
  154. if (!ctx->attributes) {
  155. ctx->attributes = emalloc(sizeof(HashTable));
  156. zend_hash_init(ctx->attributes, 0, NULL, delete_attribute, 0);
  157. }
  158. if (!ctx->attributeGroups) {
  159. ctx->attributeGroups = emalloc(sizeof(HashTable));
  160. zend_hash_init(ctx->attributeGroups, 0, NULL, delete_type, 0);
  161. }
  162. tns = get_attribute(schema->properties, "targetNamespace");
  163. if (tns == NULL) {
  164. tns = xmlSetProp(schema, BAD_CAST("targetNamespace"), BAD_CAST(""));
  165. xmlNewNs(schema, BAD_CAST(""), NULL);
  166. }
  167. trav = schema->children;
  168. while (trav != NULL) {
  169. if (node_is_equal(trav,"include")) {
  170. xmlAttrPtr location;
  171. location = get_attribute(trav->properties, "schemaLocation");
  172. if (location == NULL) {
  173. soap_error0(E_ERROR, "Parsing Schema: include has no 'schemaLocation' attribute");
  174. } else {
  175. xmlChar *uri;
  176. xmlChar *base = xmlNodeGetBase(trav->doc, trav);
  177. if (base == NULL) {
  178. uri = xmlBuildURI(location->children->content, trav->doc->URL);
  179. } else {
  180. uri = xmlBuildURI(location->children->content, base);
  181. xmlFree(base);
  182. }
  183. schema_load_file(ctx, NULL, uri, tns, 0 TSRMLS_CC);
  184. xmlFree(uri);
  185. }
  186. } else if (node_is_equal(trav,"redefine")) {
  187. xmlAttrPtr location;
  188. location = get_attribute(trav->properties, "schemaLocation");
  189. if (location == NULL) {
  190. soap_error0(E_ERROR, "Parsing Schema: redefine has no 'schemaLocation' attribute");
  191. } else {
  192. xmlChar *uri;
  193. xmlChar *base = xmlNodeGetBase(trav->doc, trav);
  194. if (base == NULL) {
  195. uri = xmlBuildURI(location->children->content, trav->doc->URL);
  196. } else {
  197. uri = xmlBuildURI(location->children->content, base);
  198. xmlFree(base);
  199. }
  200. schema_load_file(ctx, NULL, uri, tns, 0 TSRMLS_CC);
  201. xmlFree(uri);
  202. /* TODO: <redefine> support */
  203. }
  204. } else if (node_is_equal(trav,"import")) {
  205. xmlAttrPtr ns, location;
  206. xmlChar *uri = NULL;
  207. ns = get_attribute(trav->properties, "namespace");
  208. location = get_attribute(trav->properties, "schemaLocation");
  209. if (ns != NULL && tns != NULL && xmlStrcmp(ns->children->content, tns->children->content) == 0) {
  210. if (location) {
  211. soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s', namespace must not match the enclosing schema 'targetNamespace'", location->children->content);
  212. } else {
  213. soap_error0(E_ERROR, "Parsing Schema: can't import schema. Namespace must not match the enclosing schema 'targetNamespace'");
  214. }
  215. }
  216. if (location) {
  217. xmlChar *base = xmlNodeGetBase(trav->doc, trav);
  218. if (base == NULL) {
  219. uri = xmlBuildURI(location->children->content, trav->doc->URL);
  220. } else {
  221. uri = xmlBuildURI(location->children->content, base);
  222. xmlFree(base);
  223. }
  224. }
  225. schema_load_file(ctx, ns, uri, tns, 1 TSRMLS_CC);
  226. if (uri != NULL) {xmlFree(uri);}
  227. } else if (node_is_equal(trav,"annotation")) {
  228. /* TODO: <annotation> support */
  229. /* annotation cleanup
  230. xmlNodePtr tmp = trav;
  231. trav = trav->next;
  232. xmlUnlinkNode(tmp);
  233. xmlFreeNode(tmp);
  234. continue;
  235. */
  236. } else {
  237. break;
  238. }
  239. trav = trav->next;
  240. }
  241. while (trav != NULL) {
  242. if (node_is_equal(trav,"simpleType")) {
  243. schema_simpleType(ctx->sdl, tns, trav, NULL);
  244. } else if (node_is_equal(trav,"complexType")) {
  245. schema_complexType(ctx->sdl, tns, trav, NULL);
  246. } else if (node_is_equal(trav,"group")) {
  247. schema_group(ctx->sdl, tns, trav, NULL, NULL);
  248. } else if (node_is_equal(trav,"attributeGroup")) {
  249. schema_attributeGroup(ctx->sdl, tns, trav, NULL, ctx);
  250. } else if (node_is_equal(trav,"element")) {
  251. schema_element(ctx->sdl, tns, trav, NULL, NULL);
  252. } else if (node_is_equal(trav,"attribute")) {
  253. schema_attribute(ctx->sdl, tns, trav, NULL, ctx);
  254. } else if (node_is_equal(trav,"notation")) {
  255. /* TODO: <notation> support */
  256. } else if (node_is_equal(trav,"annotation")) {
  257. /* TODO: <annotation> support */
  258. } else {
  259. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in schema", trav->name);
  260. }
  261. trav = trav->next;
  262. }
  263. return TRUE;
  264. }
  265. /*
  266. <simpleType
  267. final = (#all | (list | union | restriction))
  268. id = ID
  269. name = NCName
  270. {any attributes with non-schema namespace . . .}>
  271. Content: (annotation?, (restriction | list | union))
  272. </simpleType>
  273. */
  274. static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpleType, sdlTypePtr cur_type)
  275. {
  276. xmlNodePtr trav;
  277. xmlAttrPtr name, ns;
  278. ns = get_attribute(simpleType->properties, "targetNamespace");
  279. if (ns == NULL) {
  280. ns = tns;
  281. }
  282. name = get_attribute(simpleType->properties, "name");
  283. if (cur_type != NULL) {
  284. /* Anonymous type inside <element> or <restriction> */
  285. sdlTypePtr newType, *ptr;
  286. newType = emalloc(sizeof(sdlType));
  287. memset(newType, 0, sizeof(sdlType));
  288. newType->kind = XSD_TYPEKIND_SIMPLE;
  289. if (name != NULL) {
  290. newType->name = estrdup((char*)name->children->content);
  291. newType->namens = estrdup((char*)ns->children->content);
  292. } else {
  293. newType->name = estrdup(cur_type->name);
  294. newType->namens = estrdup(cur_type->namens);
  295. }
  296. zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
  297. if (sdl->encoders == NULL) {
  298. sdl->encoders = emalloc(sizeof(HashTable));
  299. zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
  300. }
  301. cur_type->encode = emalloc(sizeof(encode));
  302. memset(cur_type->encode, 0, sizeof(encode));
  303. cur_type->encode->details.ns = estrdup(newType->namens);
  304. cur_type->encode->details.type_str = estrdup(newType->name);
  305. cur_type->encode->details.sdl_type = *ptr;
  306. cur_type->encode->to_xml = sdl_guess_convert_xml;
  307. cur_type->encode->to_zval = sdl_guess_convert_zval;
  308. zend_hash_next_index_insert(sdl->encoders, &cur_type->encode, sizeof(encodePtr), NULL);
  309. cur_type =*ptr;
  310. } else if (name != NULL) {
  311. sdlTypePtr newType, *ptr;
  312. newType = emalloc(sizeof(sdlType));
  313. memset(newType, 0, sizeof(sdlType));
  314. newType->kind = XSD_TYPEKIND_SIMPLE;
  315. newType->name = estrdup((char*)name->children->content);
  316. newType->namens = estrdup((char*)ns->children->content);
  317. if (cur_type == NULL) {
  318. zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
  319. } else {
  320. if (cur_type->elements == NULL) {
  321. cur_type->elements = emalloc(sizeof(HashTable));
  322. zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
  323. }
  324. zend_hash_update(cur_type->elements, newType->name, strlen(newType->name)+1, &newType, sizeof(sdlTypePtr), (void **)&ptr);
  325. }
  326. cur_type = (*ptr);
  327. create_encoder(sdl, cur_type, ns->children->content, name->children->content);
  328. } else {
  329. soap_error0(E_ERROR, "Parsing Schema: simpleType has no 'name' attribute");
  330. }
  331. trav = simpleType->children;
  332. if (trav != NULL && node_is_equal(trav,"annotation")) {
  333. /* TODO: <annotation> support */
  334. trav = trav->next;
  335. }
  336. if (trav != NULL) {
  337. if (node_is_equal(trav,"restriction")) {
  338. schema_restriction_simpleContent(sdl, tns, trav, cur_type, 1);
  339. trav = trav->next;
  340. } else if (node_is_equal(trav,"list")) {
  341. cur_type->kind = XSD_TYPEKIND_LIST;
  342. schema_list(sdl, tns, trav, cur_type);
  343. trav = trav->next;
  344. } else if (node_is_equal(trav,"union")) {
  345. cur_type->kind = XSD_TYPEKIND_UNION;
  346. schema_union(sdl, tns, trav, cur_type);
  347. trav = trav->next;
  348. } else {
  349. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleType", trav->name);
  350. }
  351. } else {
  352. soap_error0(E_ERROR, "Parsing Schema: expected <restriction>, <list> or <union> in simpleType");
  353. }
  354. if (trav != NULL) {
  355. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleType", trav->name);
  356. }
  357. return TRUE;
  358. }
  359. /*
  360. <list
  361. id = ID
  362. itemType = QName
  363. {any attributes with non-schema namespace . . .}>
  364. Content: (annotation?, (simpleType?))
  365. </list>
  366. */
  367. static int schema_list(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr listType, sdlTypePtr cur_type)
  368. {
  369. xmlNodePtr trav;
  370. xmlAttrPtr itemType;
  371. itemType = get_attribute(listType->properties, "itemType");
  372. if (itemType != NULL) {
  373. char *type, *ns;
  374. xmlNsPtr nsptr;
  375. parse_namespace(itemType->children->content, &type, &ns);
  376. nsptr = xmlSearchNs(listType->doc, listType, BAD_CAST(ns));
  377. if (nsptr != NULL) {
  378. sdlTypePtr newType, *tmp;
  379. newType = emalloc(sizeof(sdlType));
  380. memset(newType, 0, sizeof(sdlType));
  381. newType->name = estrdup(type);
  382. newType->namens = estrdup((char*)nsptr->href);
  383. newType->encode = get_create_encoder(sdl, newType, nsptr->href, BAD_CAST(type));
  384. if (cur_type->elements == NULL) {
  385. cur_type->elements = emalloc(sizeof(HashTable));
  386. zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
  387. }
  388. zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
  389. }
  390. if (type) {efree(type);}
  391. if (ns) {efree(ns);}
  392. }
  393. trav = listType->children;
  394. if (trav != NULL && node_is_equal(trav,"annotation")) {
  395. /* TODO: <annotation> support */
  396. trav = trav->next;
  397. }
  398. if (trav != NULL && node_is_equal(trav,"simpleType")) {
  399. sdlTypePtr newType, *tmp;
  400. if (itemType != NULL) {
  401. soap_error0(E_ERROR, "Parsing Schema: element has both 'itemType' attribute and subtype");
  402. }
  403. newType = emalloc(sizeof(sdlType));
  404. memset(newType, 0, sizeof(sdlType));
  405. newType->name = estrdup("anonymous");
  406. newType->namens = estrdup((char*)tns->children->content);
  407. if (cur_type->elements == NULL) {
  408. cur_type->elements = emalloc(sizeof(HashTable));
  409. zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
  410. }
  411. zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
  412. schema_simpleType(sdl, tns, trav, newType);
  413. trav = trav->next;
  414. }
  415. if (trav != NULL) {
  416. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in list", trav->name);
  417. }
  418. return TRUE;
  419. }
  420. /*
  421. <union
  422. id = ID
  423. memberTypes = List of QName
  424. {any attributes with non-schema namespace . . .}>
  425. Content: (annotation?, (simpleType*))
  426. </union>
  427. */
  428. static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTypePtr cur_type)
  429. {
  430. xmlNodePtr trav;
  431. xmlAttrPtr memberTypes;
  432. memberTypes = get_attribute(unionType->properties, "memberTypes");
  433. if (memberTypes != NULL) {
  434. char *str, *start, *end, *next;
  435. char *type, *ns;
  436. xmlNsPtr nsptr;
  437. str = estrdup((char*)memberTypes->children->content);
  438. whiteSpace_collapse(BAD_CAST(str));
  439. start = str;
  440. while (start != NULL && *start != '\0') {
  441. end = strchr(start,' ');
  442. if (end == NULL) {
  443. next = NULL;
  444. } else {
  445. *end = '\0';
  446. next = end+1;
  447. }
  448. parse_namespace(BAD_CAST(start), &type, &ns);
  449. nsptr = xmlSearchNs(unionType->doc, unionType, BAD_CAST(ns));
  450. if (nsptr != NULL) {
  451. sdlTypePtr newType, *tmp;
  452. newType = emalloc(sizeof(sdlType));
  453. memset(newType, 0, sizeof(sdlType));
  454. newType->name = estrdup(type);
  455. newType->namens = estrdup((char*)nsptr->href);
  456. newType->encode = get_create_encoder(sdl, newType, nsptr->href, BAD_CAST(type));
  457. if (cur_type->elements == NULL) {
  458. cur_type->elements = emalloc(sizeof(HashTable));
  459. zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
  460. }
  461. zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
  462. }
  463. if (type) {efree(type);}
  464. if (ns) {efree(ns);}
  465. start = next;
  466. }
  467. efree(str);
  468. }
  469. trav = unionType->children;
  470. if (trav != NULL && node_is_equal(trav,"annotation")) {
  471. /* TODO: <annotation> support */
  472. trav = trav->next;
  473. }
  474. while (trav != NULL) {
  475. if (node_is_equal(trav,"simpleType")) {
  476. sdlTypePtr newType, *tmp;
  477. newType = emalloc(sizeof(sdlType));
  478. memset(newType, 0, sizeof(sdlType));
  479. newType->name = estrdup("anonymous");
  480. newType->namens = estrdup((char*)tns->children->content);
  481. if (cur_type->elements == NULL) {
  482. cur_type->elements = emalloc(sizeof(HashTable));
  483. zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
  484. }
  485. zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
  486. schema_simpleType(sdl, tns, trav, newType);
  487. } else {
  488. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
  489. }
  490. trav = trav->next;
  491. }
  492. if (trav != NULL) {
  493. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
  494. }
  495. return TRUE;
  496. }
  497. /*
  498. <simpleContent
  499. id = ID
  500. {any attributes with non-schema namespace . . .}>
  501. Content: (annotation?, (restriction | extension))
  502. </simpleContent>
  503. */
  504. static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompType, sdlTypePtr cur_type)
  505. {
  506. xmlNodePtr trav;
  507. trav = simpCompType->children;
  508. if (trav != NULL && node_is_equal(trav,"annotation")) {
  509. /* TODO: <annotation> support */
  510. trav = trav->next;
  511. }
  512. if (trav != NULL) {
  513. if (node_is_equal(trav, "restriction")) {
  514. cur_type->kind = XSD_TYPEKIND_RESTRICTION;
  515. schema_restriction_simpleContent(sdl, tns, trav, cur_type, 0);
  516. trav = trav->next;
  517. } else if (node_is_equal(trav, "extension")) {
  518. cur_type->kind = XSD_TYPEKIND_EXTENSION;
  519. schema_extension_simpleContent(sdl, tns, trav, cur_type);
  520. trav = trav->next;
  521. } else {
  522. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
  523. }
  524. } else {
  525. soap_error0(E_ERROR, "Parsing Schema: expected <restriction> or <extension> in simpleContent");
  526. }
  527. if (trav != NULL) {
  528. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
  529. }
  530. return TRUE;
  531. }
  532. /*
  533. simpleType:<restriction
  534. base = QName
  535. id = ID
  536. {any attributes with non-schema namespace . . .}>
  537. Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?)
  538. </restriction>
  539. simpleContent:<restriction
  540. base = QName
  541. id = ID
  542. {any attributes with non-schema namespace . . .}>
  543. Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))
  544. </restriction>
  545. */
  546. static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType)
  547. {
  548. xmlNodePtr trav;
  549. xmlAttrPtr base;
  550. base = get_attribute(restType->properties, "base");
  551. if (base != NULL) {
  552. char *type, *ns;
  553. xmlNsPtr nsptr;
  554. parse_namespace(base->children->content, &type, &ns);
  555. nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
  556. if (nsptr != NULL) {
  557. cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
  558. }
  559. if (type) {efree(type);}
  560. if (ns) {efree(ns);}
  561. } else if (!simpleType) {
  562. soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
  563. }
  564. if (cur_type->restrictions == NULL) {
  565. cur_type->restrictions = emalloc(sizeof(sdlRestrictions));
  566. memset(cur_type->restrictions, 0, sizeof(sdlRestrictions));
  567. }
  568. trav = restType->children;
  569. if (trav != NULL && node_is_equal(trav, "annotation")) {
  570. /* TODO: <annotation> support */
  571. trav = trav->next;
  572. }
  573. if (trav != NULL && node_is_equal(trav, "simpleType")) {
  574. schema_simpleType(sdl, tns, trav, cur_type);
  575. trav = trav->next;
  576. }
  577. while (trav != NULL) {
  578. if (node_is_equal(trav, "minExclusive")) {
  579. schema_restriction_var_int(trav, &cur_type->restrictions->minExclusive);
  580. } else if (node_is_equal(trav, "minInclusive")) {
  581. schema_restriction_var_int(trav, &cur_type->restrictions->minInclusive);
  582. } else if (node_is_equal(trav, "maxExclusive")) {
  583. schema_restriction_var_int(trav, &cur_type->restrictions->maxExclusive);
  584. } else if (node_is_equal(trav, "maxInclusive")) {
  585. schema_restriction_var_int(trav, &cur_type->restrictions->maxInclusive);
  586. } else if (node_is_equal(trav, "totalDigits")) {
  587. schema_restriction_var_int(trav, &cur_type->restrictions->totalDigits);
  588. } else if (node_is_equal(trav, "fractionDigits")) {
  589. schema_restriction_var_int(trav, &cur_type->restrictions->fractionDigits);
  590. } else if (node_is_equal(trav, "length")) {
  591. schema_restriction_var_int(trav, &cur_type->restrictions->length);
  592. } else if (node_is_equal(trav, "minLength")) {
  593. schema_restriction_var_int(trav, &cur_type->restrictions->minLength);
  594. } else if (node_is_equal(trav, "maxLength")) {
  595. schema_restriction_var_int(trav, &cur_type->restrictions->maxLength);
  596. } else if (node_is_equal(trav, "whiteSpace")) {
  597. schema_restriction_var_char(trav, &cur_type->restrictions->whiteSpace);
  598. } else if (node_is_equal(trav, "pattern")) {
  599. schema_restriction_var_char(trav, &cur_type->restrictions->pattern);
  600. } else if (node_is_equal(trav, "enumeration")) {
  601. sdlRestrictionCharPtr enumval = NULL;
  602. schema_restriction_var_char(trav, &enumval);
  603. if (cur_type->restrictions->enumeration == NULL) {
  604. cur_type->restrictions->enumeration = emalloc(sizeof(HashTable));
  605. zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_restriction_var_char, 0);
  606. }
  607. zend_hash_add(cur_type->restrictions->enumeration, enumval->value, strlen(enumval->value)+1, &enumval, sizeof(sdlRestrictionCharPtr), NULL);
  608. } else {
  609. break;
  610. }
  611. trav = trav->next;
  612. }
  613. if (!simpleType) {
  614. while (trav != NULL) {
  615. if (node_is_equal(trav,"attribute")) {
  616. schema_attribute(sdl, tns, trav, cur_type, NULL);
  617. } else if (node_is_equal(trav,"attributeGroup")) {
  618. schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
  619. } else if (node_is_equal(trav,"anyAttribute")) {
  620. /* TODO: <anyAttribute> support */
  621. trav = trav->next;
  622. break;
  623. } else {
  624. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
  625. }
  626. trav = trav->next;
  627. }
  628. }
  629. if (trav != NULL) {
  630. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
  631. }
  632. return TRUE;
  633. }
  634. /*
  635. <restriction
  636. base = QName
  637. id = ID
  638. {any attributes with non-schema namespace . . .}>
  639. Content: (annotation?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))
  640. </restriction>
  641. */
  642. static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type)
  643. {
  644. xmlAttrPtr base;
  645. xmlNodePtr trav;
  646. base = get_attribute(restType->properties, "base");
  647. if (base != NULL) {
  648. char *type, *ns;
  649. xmlNsPtr nsptr;
  650. parse_namespace(base->children->content, &type, &ns);
  651. nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
  652. if (nsptr != NULL) {
  653. cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
  654. }
  655. if (type) {efree(type);}
  656. if (ns) {efree(ns);}
  657. } else {
  658. soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
  659. }
  660. trav = restType->children;
  661. if (trav != NULL && node_is_equal(trav,"annotation")) {
  662. /* TODO: <annotation> support */
  663. trav = trav->next;
  664. }
  665. if (trav != NULL) {
  666. if (node_is_equal(trav,"group")) {
  667. schema_group(sdl, tns, trav, cur_type, NULL);
  668. trav = trav->next;
  669. } else if (node_is_equal(trav,"all")) {
  670. schema_all(sdl, tns, trav, cur_type, NULL);
  671. trav = trav->next;
  672. } else if (node_is_equal(trav,"choice")) {
  673. schema_choice(sdl, tns, trav, cur_type, NULL);
  674. trav = trav->next;
  675. } else if (node_is_equal(trav,"sequence")) {
  676. schema_sequence(sdl, tns, trav, cur_type, NULL);
  677. trav = trav->next;
  678. }
  679. }
  680. while (trav != NULL) {
  681. if (node_is_equal(trav,"attribute")) {
  682. schema_attribute(sdl, tns, trav, cur_type, NULL);
  683. } else if (node_is_equal(trav,"attributeGroup")) {
  684. schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
  685. } else if (node_is_equal(trav,"anyAttribute")) {
  686. /* TODO: <anyAttribute> support */
  687. trav = trav->next;
  688. break;
  689. } else {
  690. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
  691. }
  692. trav = trav->next;
  693. }
  694. if (trav != NULL) {
  695. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
  696. }
  697. return TRUE;
  698. }
  699. static int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr)
  700. {
  701. xmlAttrPtr fixed, value;
  702. if ((*valptr) == NULL) {
  703. (*valptr) = emalloc(sizeof(sdlRestrictionInt));
  704. }
  705. memset((*valptr), 0, sizeof(sdlRestrictionInt));
  706. fixed = get_attribute(val->properties, "fixed");
  707. (*valptr)->fixed = FALSE;
  708. if (fixed != NULL) {
  709. if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
  710. !strncmp((char*)fixed->children->content, "1", sizeof("1")))
  711. (*valptr)->fixed = TRUE;
  712. }
  713. value = get_attribute(val->properties, "value");
  714. if (value == NULL) {
  715. soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
  716. }
  717. (*valptr)->value = atoi((char*)value->children->content);
  718. return TRUE;
  719. }
  720. static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr)
  721. {
  722. xmlAttrPtr fixed, value;
  723. if ((*valptr) == NULL) {
  724. (*valptr) = emalloc(sizeof(sdlRestrictionChar));
  725. }
  726. memset((*valptr), 0, sizeof(sdlRestrictionChar));
  727. fixed = get_attribute(val->properties, "fixed");
  728. (*valptr)->fixed = FALSE;
  729. if (fixed != NULL) {
  730. if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
  731. !strncmp((char*)fixed->children->content, "1", sizeof("1"))) {
  732. (*valptr)->fixed = TRUE;
  733. }
  734. }
  735. value = get_attribute(val->properties, "value");
  736. if (value == NULL) {
  737. soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
  738. }
  739. (*valptr)->value = estrdup((char*)value->children->content);
  740. return TRUE;
  741. }
  742. /*
  743. From simpleContent (not supported):
  744. <extension
  745. base = QName
  746. id = ID
  747. {any attributes with non-schema namespace . . .}>
  748. Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
  749. </extension>
  750. */
  751. static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
  752. {
  753. xmlNodePtr trav;
  754. xmlAttrPtr base;
  755. base = get_attribute(extType->properties, "base");
  756. if (base != NULL) {
  757. char *type, *ns;
  758. xmlNsPtr nsptr;
  759. parse_namespace(base->children->content, &type, &ns);
  760. nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
  761. if (nsptr != NULL) {
  762. cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
  763. }
  764. if (type) {efree(type);}
  765. if (ns) {efree(ns);}
  766. } else {
  767. soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
  768. }
  769. trav = extType->children;
  770. if (trav != NULL && node_is_equal(trav,"annotation")) {
  771. /* TODO: <annotation> support */
  772. trav = trav->next;
  773. }
  774. while (trav != NULL) {
  775. if (node_is_equal(trav,"attribute")) {
  776. schema_attribute(sdl, tns, trav, cur_type, NULL);
  777. } else if (node_is_equal(trav,"attributeGroup")) {
  778. schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
  779. } else if (node_is_equal(trav,"anyAttribute")) {
  780. /* TODO: <anyAttribute> support */
  781. trav = trav->next;
  782. break;
  783. } else {
  784. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
  785. }
  786. trav = trav->next;
  787. }
  788. if (trav != NULL) {
  789. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
  790. }
  791. return TRUE;
  792. }
  793. /*
  794. From complexContent:
  795. <extension
  796. base = QName
  797. id = ID
  798. {any attributes with non-schema namespace . . .}>
  799. Content: (annotation?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))
  800. </extension>
  801. */
  802. static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
  803. {
  804. xmlNodePtr trav;
  805. xmlAttrPtr base;
  806. base = get_attribute(extType->properties, "base");
  807. if (base != NULL) {
  808. char *type, *ns;
  809. xmlNsPtr nsptr;
  810. parse_namespace(base->children->content, &type, &ns);
  811. nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
  812. if (nsptr != NULL) {
  813. cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
  814. }
  815. if (type) {efree(type);}
  816. if (ns) {efree(ns);}
  817. } else {
  818. soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
  819. }
  820. trav = extType->children;
  821. if (trav != NULL && node_is_equal(trav,"annotation")) {
  822. /* TODO: <annotation> support */
  823. trav = trav->next;
  824. }
  825. if (trav != NULL) {
  826. if (node_is_equal(trav,"group")) {
  827. schema_group(sdl, tns, trav, cur_type, NULL);
  828. trav = trav->next;
  829. } else if (node_is_equal(trav,"all")) {
  830. schema_all(sdl, tns, trav, cur_type, NULL);
  831. trav = trav->next;
  832. } else if (node_is_equal(trav,"choice")) {
  833. schema_choice(sdl, tns, trav, cur_type, NULL);
  834. trav = trav->next;
  835. } else if (node_is_equal(trav,"sequence")) {
  836. schema_sequence(sdl, tns, trav, cur_type, NULL);
  837. trav = trav->next;
  838. }
  839. }
  840. while (trav != NULL) {
  841. if (node_is_equal(trav,"attribute")) {
  842. schema_attribute(sdl, tns, trav, cur_type, NULL);
  843. } else if (node_is_equal(trav,"attributeGroup")) {
  844. schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
  845. } else if (node_is_equal(trav,"anyAttribute")) {
  846. /* TODO: <anyAttribute> support */
  847. trav = trav->next;
  848. break;
  849. } else {
  850. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
  851. }
  852. trav = trav->next;
  853. }
  854. if (trav != NULL) {
  855. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
  856. }
  857. return TRUE;
  858. }
  859. void schema_min_max(xmlNodePtr node, sdlContentModelPtr model)
  860. {
  861. xmlAttrPtr attr = get_attribute(node->properties, "minOccurs");
  862. if (attr) {
  863. model->min_occurs = atoi((char*)attr->children->content);
  864. } else {
  865. model->min_occurs = 1;
  866. }
  867. attr = get_attribute(node->properties, "maxOccurs");
  868. if (attr) {
  869. if (!strncmp((char*)attr->children->content, "unbounded", sizeof("unbounded"))) {
  870. model->max_occurs = -1;
  871. } else {
  872. model->max_occurs = atoi((char*)attr->children->content);
  873. }
  874. } else {
  875. model->max_occurs = 1;
  876. }
  877. }
  878. /*
  879. <all
  880. id = ID
  881. maxOccurs = 1 : 1
  882. minOccurs = (0 | 1) : 1
  883. {any attributes with non-schema namespace . . .}>
  884. Content: (annotation?, element*)
  885. </all>
  886. */
  887. static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr all, sdlTypePtr cur_type, sdlContentModelPtr model)
  888. {
  889. xmlNodePtr trav;
  890. sdlContentModelPtr newModel;
  891. newModel = emalloc(sizeof(sdlContentModel));
  892. newModel->kind = XSD_CONTENT_ALL;
  893. newModel->u.content = emalloc(sizeof(HashTable));
  894. zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
  895. if (model == NULL) {
  896. cur_type->model = newModel;
  897. } else {
  898. zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
  899. }
  900. schema_min_max(all, newModel);
  901. trav = all->children;
  902. if (trav != NULL && node_is_equal(trav,"annotation")) {
  903. /* TODO: <annotation> support */
  904. trav = trav->next;
  905. }
  906. while (trav != NULL) {
  907. if (node_is_equal(trav,"element")) {
  908. schema_element(sdl, tns, trav, cur_type, newModel);
  909. } else {
  910. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in all", trav->name);
  911. }
  912. trav = trav->next;
  913. }
  914. return TRUE;
  915. }
  916. /*
  917. <group
  918. name = NCName
  919. Content: (annotation?, (all | choice | sequence))
  920. </group>
  921. <group
  922. name = NCName
  923. ref = QName>
  924. Content: (annotation?)
  925. </group>
  926. */
  927. static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTypePtr cur_type, sdlContentModelPtr model)
  928. {
  929. xmlNodePtr trav;
  930. xmlAttrPtr ns, name, ref = NULL;
  931. sdlContentModelPtr newModel;
  932. ns = get_attribute(groupType->properties, "targetNamespace");
  933. if (ns == NULL) {
  934. ns = tns;
  935. }
  936. name = get_attribute(groupType->properties, "name");
  937. if (name == NULL) {
  938. name = ref = get_attribute(groupType->properties, "ref");
  939. }
  940. if (name) {
  941. smart_str key = {0};
  942. if (ref) {
  943. char *type, *ns;
  944. xmlNsPtr nsptr;
  945. parse_namespace(ref->children->content, &type, &ns);
  946. nsptr = xmlSearchNs(groupType->doc, groupType, BAD_CAST(ns));
  947. if (nsptr != NULL) {
  948. smart_str_appends(&key, (char*)nsptr->href);
  949. smart_str_appendc(&key, ':');
  950. }
  951. smart_str_appends(&key, type);
  952. smart_str_0(&key);
  953. newModel = emalloc(sizeof(sdlContentModel));
  954. newModel->kind = XSD_CONTENT_GROUP_REF;
  955. newModel->u.group_ref = estrdup(key.c);
  956. if (type) {efree(type);}
  957. if (ns) {efree(ns);}
  958. } else {
  959. newModel = emalloc(sizeof(sdlContentModel));
  960. newModel->kind = XSD_CONTENT_SEQUENCE; /* will be redefined */
  961. newModel->u.content = emalloc(sizeof(HashTable));
  962. zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
  963. smart_str_appends(&key, (char*)ns->children->content);
  964. smart_str_appendc(&key, ':');
  965. smart_str_appends(&key, (char*)name->children->content);
  966. smart_str_0(&key);
  967. }
  968. if (cur_type == NULL) {
  969. sdlTypePtr newType;
  970. newType = emalloc(sizeof(sdlType));
  971. memset(newType, 0, sizeof(sdlType));
  972. if (sdl->groups == NULL) {
  973. sdl->groups = emalloc(sizeof(HashTable));
  974. zend_hash_init(sdl->groups, 0, NULL, delete_type, 0);
  975. }
  976. if (zend_hash_add(sdl->groups, key.c, key.len+1, (void**)&newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
  977. soap_error1(E_ERROR, "Parsing Schema: group '%s' already defined", key.c);
  978. }
  979. cur_type = newType;
  980. }
  981. smart_str_free(&key);
  982. if (model == NULL) {
  983. cur_type->model = newModel;
  984. } else {
  985. zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
  986. }
  987. } else {
  988. soap_error0(E_ERROR, "Parsing Schema: group has no 'name' nor 'ref' attributes");
  989. }
  990. schema_min_max(groupType, newModel);
  991. trav = groupType->children;
  992. if (trav != NULL && node_is_equal(trav,"annotation")) {
  993. /* TODO: <annotation> support */
  994. trav = trav->next;
  995. }
  996. if (trav != NULL) {
  997. if (node_is_equal(trav,"choice")) {
  998. if (ref != NULL) {
  999. soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
  1000. }
  1001. newModel->kind = XSD_CONTENT_CHOICE;
  1002. schema_choice(sdl, tns, trav, cur_type, newModel);
  1003. trav = trav->next;
  1004. } else if (node_is_equal(trav,"sequence")) {
  1005. if (ref != NULL) {
  1006. soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
  1007. }
  1008. newModel->kind = XSD_CONTENT_SEQUENCE;
  1009. schema_sequence(sdl, tns, trav, cur_type, newModel);
  1010. trav = trav->next;
  1011. } else if (node_is_equal(trav,"all")) {
  1012. if (ref != NULL) {
  1013. soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
  1014. }
  1015. newModel->kind = XSD_CONTENT_ALL;
  1016. schema_all(sdl, tns, trav, cur_type, newModel);
  1017. trav = trav->next;
  1018. } else {
  1019. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
  1020. }
  1021. }
  1022. if (trav != NULL) {
  1023. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
  1024. }
  1025. return TRUE;
  1026. }
  1027. /*
  1028. <choice
  1029. id = ID
  1030. maxOccurs = (nonNegativeInteger | unbounded) : 1
  1031. minOccurs = nonNegativeInteger : 1
  1032. {any attributes with non-schema namespace . . .}>
  1033. Content: (annotation?, (element | group | choice | sequence | any)*)
  1034. </choice>
  1035. */
  1036. static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model)
  1037. {
  1038. xmlNodePtr trav;
  1039. sdlContentModelPtr newModel;
  1040. newModel = emalloc(sizeof(sdlContentModel));
  1041. newModel->kind = XSD_CONTENT_CHOICE;
  1042. newModel->u.content = emalloc(sizeof(HashTable));
  1043. zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
  1044. if (model == NULL) {
  1045. cur_type->model = newModel;
  1046. } else {
  1047. zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
  1048. }
  1049. schema_min_max(choiceType, newModel);
  1050. trav = choiceType->children;
  1051. if (trav != NULL && node_is_equal(trav,"annotation")) {
  1052. /* TODO: <annotation> support */
  1053. trav = trav->next;
  1054. }
  1055. while (trav != NULL) {
  1056. if (node_is_equal(trav,"element")) {
  1057. schema_element(sdl, tns, trav, cur_type, newModel);
  1058. } else if (node_is_equal(trav,"group")) {
  1059. schema_group(sdl, tns, trav, cur_type, newModel);
  1060. } else if (node_is_equal(trav,"choice")) {
  1061. schema_choice(sdl, tns, trav, cur_type, newModel);
  1062. } else if (node_is_equal(trav,"sequence")) {
  1063. schema_sequence(sdl, tns, trav, cur_type, newModel);
  1064. } else if (node_is_equal(trav,"any")) {
  1065. schema_any(sdl, tns, trav, cur_type, newModel);
  1066. } else {
  1067. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in choice", trav->name);
  1068. }
  1069. trav = trav->next;
  1070. }
  1071. return TRUE;
  1072. }
  1073. /*
  1074. <sequence
  1075. id = ID
  1076. maxOccurs = (nonNegativeInteger | unbounded) : 1
  1077. minOccurs = nonNegativeInteger : 1
  1078. {any attributes with non-schema namespace . . .}>
  1079. Content: (annotation?, (element | group | choice | sequence | any)*)
  1080. </sequence>
  1081. */
  1082. static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model)
  1083. {
  1084. xmlNodePtr trav;
  1085. sdlContentModelPtr newModel;
  1086. newModel = emalloc(sizeof(sdlContentModel));
  1087. newModel->kind = XSD_CONTENT_SEQUENCE;
  1088. newModel->u.content = emalloc(sizeof(HashTable));
  1089. zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
  1090. if (model == NULL) {
  1091. cur_type->model = newModel;
  1092. } else {
  1093. zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
  1094. }
  1095. schema_min_max(seqType, newModel);
  1096. trav = seqType->children;
  1097. if (trav != NULL && node_is_equal(trav,"annotation")) {
  1098. /* TODO: <annotation> support */
  1099. trav = trav->next;
  1100. }
  1101. while (trav != NULL) {
  1102. if (node_is_equal(trav,"element")) {
  1103. schema_element(sdl, tns, trav, cur_type, newModel);
  1104. } else if (node_is_equal(trav,"group")) {
  1105. schema_group(sdl, tns, trav, cur_type, newModel);
  1106. } else if (node_is_equal(trav,"choice")) {
  1107. schema_choice(sdl, tns, trav, cur_type, newModel);
  1108. } else if (node_is_equal(trav,"sequence")) {
  1109. schema_sequence(sdl, tns, trav, cur_type, newModel);
  1110. } else if (node_is_equal(trav,"any")) {
  1111. schema_any(sdl, tns, trav, cur_type, newModel);
  1112. } else {
  1113. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in sequence", trav->name);
  1114. }
  1115. trav = trav->next;
  1116. }
  1117. return TRUE;
  1118. }
  1119. /*
  1120. <any
  1121. id = ID
  1122. maxOccurs = (nonNegativeInteger | unbounded) : 1
  1123. minOccurs = nonNegativeInteger : 1
  1124. namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) : ##any
  1125. processContents = (lax | skip | strict) : strict
  1126. {any attributes with non-schema namespace . . .}>
  1127. Content: (annotation?)
  1128. </any>
  1129. */
  1130. static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr anyType, sdlTypePtr cur_type, sdlContentModelPtr model)
  1131. {
  1132. if (model != NULL) {
  1133. sdlContentModelPtr newModel;
  1134. newModel = emalloc(sizeof(sdlContentModel));
  1135. newModel->kind = XSD_CONTENT_ANY;
  1136. schema_min_max(anyType, newModel);
  1137. zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
  1138. }
  1139. return TRUE;
  1140. }
  1141. /*
  1142. <complexContent
  1143. id = ID
  1144. mixed = boolean
  1145. {any attributes with non-schema namespace . . .}>
  1146. Content: (annotation?, (restriction | extension))
  1147. </complexContent>
  1148. */
  1149. static int schema_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compCont, sdlTypePtr cur_type)
  1150. {
  1151. xmlNodePtr trav;
  1152. trav = compCont->children;
  1153. if (trav != NULL && node_is_equal(trav,"annotation")) {
  1154. /* TODO: <annotation> support */
  1155. trav = trav->next;
  1156. }
  1157. if (trav != NULL) {
  1158. if (node_is_equal(trav, "restriction")) {
  1159. cur_type->kind = XSD_TYPEKIND_RESTRICTION;
  1160. schema_restriction_complexContent(sdl, tns, trav, cur_type);
  1161. trav = trav->next;
  1162. } else if (node_is_equal(trav, "extension")) {
  1163. cur_type->kind = XSD_TYPEKIND_EXTENSION;
  1164. schema_extension_complexContent(sdl, tns, trav, cur_type);
  1165. trav = trav->next;
  1166. } else {
  1167. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
  1168. }
  1169. } else {
  1170. soap_error0(E_ERROR, "Parsing Schema: <restriction> or <extension> expected in complexContent");
  1171. }
  1172. if (trav != NULL) {
  1173. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
  1174. }
  1175. return TRUE;
  1176. }
  1177. /*
  1178. <complexType
  1179. abstract = boolean : false
  1180. block = (#all | List of (extension | restriction))
  1181. final = (#all | List of (extension | restriction))
  1182. id = ID
  1183. mixed = boolean : false
  1184. name = NCName
  1185. {any attributes with non-schema namespace . . .}>
  1186. Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
  1187. </complexType>
  1188. */
  1189. static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type)
  1190. {
  1191. xmlNodePtr trav;
  1192. xmlAttrPtr attrs, name, ns;
  1193. attrs = compType->properties;
  1194. ns = get_attribute(attrs, "targetNamespace");
  1195. if (ns == NULL) {
  1196. ns = tns;
  1197. }
  1198. name = get_attribute(attrs, "name");
  1199. if (cur_type != NULL) {
  1200. /* Anonymous type inside <element> */
  1201. sdlTypePtr newType, *ptr;
  1202. newType = emalloc(sizeof(sdlType));
  1203. memset(newType, 0, sizeof(sdlType));
  1204. newType->kind = XSD_TYPEKIND_COMPLEX;
  1205. if (name != NULL) {
  1206. newType->name = estrdup((char*)name->children->content);
  1207. newType->namens = estrdup((char*)ns->children->content);
  1208. } else {
  1209. newType->name = estrdup(cur_type->name);
  1210. newType->namens = estrdup(cur_type->namens);
  1211. }
  1212. zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
  1213. if (sdl->encoders == NULL) {
  1214. sdl->encoders = emalloc(sizeof(HashTable));
  1215. zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
  1216. }
  1217. cur_type->encode = emalloc(sizeof(encode));
  1218. memset(cur_type->encode, 0, sizeof(encode));
  1219. cur_type->encode->details.ns = estrdup(newType->namens);
  1220. cur_type->encode->details.type_str = estrdup(newType->name);
  1221. cur_type->encode->details.sdl_type = *ptr;
  1222. cur_type->encode->to_xml = sdl_guess_convert_xml;
  1223. cur_type->encode->to_zval = sdl_guess_convert_zval;
  1224. zend_hash_next_index_insert(sdl->encoders, &cur_type->encode, sizeof(encodePtr), NULL);
  1225. cur_type =*ptr;
  1226. } else if (name) {
  1227. sdlTypePtr newType, *ptr;
  1228. newType = emalloc(sizeof(sdlType));
  1229. memset(newType, 0, sizeof(sdlType));
  1230. newType->kind = XSD_TYPEKIND_COMPLEX;
  1231. newType->name = estrdup((char*)name->children->content);
  1232. newType->namens = estrdup((char*)ns->children->content);
  1233. zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
  1234. cur_type = (*ptr);
  1235. create_encoder(sdl, cur_type, ns->children->content, name->children->content);
  1236. } else {
  1237. soap_error0(E_ERROR, "Parsing Schema: complexType has no 'name' attribute");
  1238. return FALSE;
  1239. }
  1240. trav = compType->children;
  1241. if (trav != NULL && node_is_equal(trav, "annotation")) {
  1242. /* TODO: <annotation> support */
  1243. trav = trav->next;
  1244. }
  1245. if (trav != NULL) {
  1246. if (node_is_equal(trav,"simpleContent")) {
  1247. schema_simpleContent(sdl, tns, trav, cur_type);
  1248. trav = trav->next;
  1249. } else if (node_is_equal(trav,"complexContent")) {
  1250. schema_complexContent(sdl, tns, trav, cur_type);
  1251. trav = trav->next;
  1252. } else {
  1253. if (node_is_equal(trav,"group")) {
  1254. schema_group(sdl, tns, trav, cur_type, NULL);
  1255. trav = trav->next;
  1256. } else if (node_is_equal(trav,"all")) {
  1257. schema_all(sdl, tns, trav, cur_type, NULL);
  1258. trav = trav->next;
  1259. } else if (node_is_equal(trav,"choice")) {
  1260. schema_choice(sdl, tns, trav, cur_type, NULL);
  1261. trav = trav->next;
  1262. } else if (node_is_equal(trav,"sequence")) {
  1263. schema_sequence(sdl, tns, trav, cur_type, NULL);
  1264. trav = trav->next;
  1265. }
  1266. while (trav != NULL) {
  1267. if (node_is_equal(trav,"attribute")) {
  1268. schema_attribute(sdl, tns, trav, cur_type, NULL);
  1269. } else if (node_is_equal(trav,"attributeGroup")) {
  1270. schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
  1271. } else if (node_is_equal(trav,"anyAttribute")) {
  1272. /* TODO: <anyAttribute> support */
  1273. trav = trav->next;
  1274. break;
  1275. } else {
  1276. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
  1277. }
  1278. trav = trav->next;
  1279. }
  1280. }
  1281. }
  1282. if (trav != NULL) {
  1283. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
  1284. }
  1285. return TRUE;
  1286. }
  1287. /*
  1288. <element
  1289. abstract = boolean : false
  1290. block = (#all | List of (extension | restriction | substitution))
  1291. default = string
  1292. final = (#all | List of (extension | restriction))
  1293. fixed = string
  1294. form = (qualified | unqualified)
  1295. id = ID
  1296. maxOccurs = (nonNegativeInteger | unbounded) : 1
  1297. minOccurs = nonNegativeInteger : 1
  1298. name = NCName
  1299. nillable = boolean : false
  1300. ref = QName
  1301. substitutionGroup = QName
  1302. type = QName
  1303. {any attributes with non-schema namespace . . .}>
  1304. Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
  1305. </element>
  1306. */
  1307. static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model)
  1308. {
  1309. xmlNodePtr trav;
  1310. xmlAttrPtr attrs, attr, ns, name, type, ref = NULL;
  1311. attrs = element->properties;
  1312. ns = get_attribute(attrs, "targetNamespace");
  1313. if (ns == NULL) {
  1314. ns = tns;
  1315. }
  1316. name = get_attribute(attrs, "name");
  1317. if (name == NULL) {
  1318. name = ref = get_attribute(attrs, "ref");
  1319. }
  1320. if (name) {
  1321. HashTable *addHash;
  1322. sdlTypePtr newType;
  1323. smart_str key = {0};
  1324. newType = emalloc(sizeof(sdlType));
  1325. memset(newType, 0, sizeof(sdlType));
  1326. if (ref) {
  1327. smart_str nscat = {0};
  1328. char *type, *ns;
  1329. xmlNsPtr nsptr;
  1330. parse_namespace(ref->children->content, &type, &ns);
  1331. nsptr = xmlSearchNs(element->doc, element, BAD_CAST(ns));
  1332. if (nsptr != NULL) {
  1333. smart_str_appends(&nscat, (char*)nsptr->href);
  1334. smart_str_appendc(&nscat, ':');
  1335. newType->namens = estrdup((char*)nsptr->href);
  1336. }
  1337. smart_str_appends(&nscat, type);
  1338. newType->name = estrdup(type);
  1339. smart_str_0(&nscat);
  1340. if (type) {efree(type);}
  1341. if (ns) {efree(ns);}
  1342. newType->ref = estrdup(nscat.c);
  1343. smart_str_free(&nscat);
  1344. } else {
  1345. newType->name = estrdup((char*)name->children->content);
  1346. newType->namens = estrdup((char*)ns->children->content);
  1347. }
  1348. newType->nillable = FALSE;
  1349. if (cur_type == NULL) {
  1350. if (sdl->elements == NULL) {
  1351. sdl->elements = emalloc(sizeof(HashTable));
  1352. zend_hash_init(sdl->elements, 0, NULL, delete_type, 0);
  1353. }
  1354. addHash = sdl->elements;
  1355. smart_str_appends(&key, newType->namens);
  1356. smart_str_appendc(&key, ':');
  1357. smart_str_appends(&key, newType->name);
  1358. } else {
  1359. if (cur_type->elements == NULL) {
  1360. cur_type->elements = emalloc(sizeof(HashTable));
  1361. zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
  1362. }
  1363. addHash = cur_type->elements;
  1364. smart_str_appends(&key, newType->name);
  1365. }
  1366. smart_str_0(&key);
  1367. if (zend_hash_add(addHash, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
  1368. if (cur_type == NULL) {
  1369. soap_error1(E_ERROR, "Parsing Schema: element '%s' already defined", key.c);
  1370. } else {
  1371. zend_hash_next_index_insert(addHash, &newType, sizeof(sdlTypePtr), NULL);
  1372. }
  1373. }
  1374. smart_str_free(&key);
  1375. if (model != NULL) {
  1376. sdlContentModelPtr newModel = emalloc(sizeof(sdlContentModel));
  1377. newModel->kind = XSD_CONTENT_ELEMENT;
  1378. newModel->u.element = newType;
  1379. schema_min_max(element, newModel);
  1380. zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
  1381. }
  1382. cur_type = newType;
  1383. } else {
  1384. soap_error0(E_ERROR, "Parsing Schema: element has no 'name' nor 'ref' attributes");
  1385. }
  1386. /* nillable = boolean : false */
  1387. attrs = element->properties;
  1388. attr = get_attribute(attrs, "nillable");
  1389. if (attr) {
  1390. if (ref != NULL) {
  1391. soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'nillable' attributes");
  1392. }
  1393. if (!stricmp((char*)attr->children->content, "true") ||
  1394. !stricmp((char*)attr->children->content, "1")) {
  1395. cur_type->nillable = TRUE;
  1396. } else {
  1397. cur_type->nillable = FALSE;
  1398. }
  1399. } else {
  1400. cur_type->nillable = FALSE;
  1401. }
  1402. attr = get_attribute(attrs, "fixed");
  1403. if (attr) {
  1404. if (ref != NULL) {
  1405. soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
  1406. }
  1407. cur_type->fixed = estrdup((char*)attr->children->content);
  1408. }
  1409. attr = get_attribute(attrs, "default");
  1410. if (attr) {
  1411. if (ref != NULL) {
  1412. soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
  1413. } else if (ref != NULL) {
  1414. soap_error0(E_ERROR, "Parsing Schema: element has both 'default' and 'fixed' attributes");
  1415. }
  1416. cur_type->def = estrdup((char*)attr->children->content);
  1417. }
  1418. /* form */
  1419. attr = get_attribute(attrs, "form");
  1420. if (attr) {
  1421. if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
  1422. cur_type->form = XSD_FORM_QUALIFIED;
  1423. } else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
  1424. cur_type->form = XSD_FORM_UNQUALIFIED;
  1425. } else {
  1426. cur_type->form = XSD_FORM_DEFAULT;
  1427. }
  1428. } else {
  1429. cur_type->form = XSD_FORM_DEFAULT;
  1430. }
  1431. if (cur_type->form == XSD_FORM_DEFAULT) {
  1432. xmlNodePtr parent = element->parent;
  1433. while (parent) {
  1434. if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
  1435. xmlAttrPtr def;
  1436. def = get_attribute(parent->properties, "elementFormDefault");
  1437. if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
  1438. cur_type->form = XSD_FORM_UNQUALIFIED;
  1439. } else {
  1440. cur_type->form = XSD_FORM_QUALIFIED;
  1441. }
  1442. break;
  1443. }
  1444. parent = parent->parent;
  1445. }
  1446. if (parent == NULL) {
  1447. cur_type->form = XSD_FORM_UNQUALIFIED;
  1448. }
  1449. }
  1450. /* type = QName */
  1451. type = get_attribute(attrs, "type");
  1452. if (type) {
  1453. char *cptype, *str_ns;
  1454. xmlNsPtr nsptr;
  1455. if (ref != NULL) {
  1456. soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'type' attributes");
  1457. }
  1458. parse_namespace(type->children->content, &cptype, &str_ns);
  1459. nsptr = xmlSearchNs(element->doc, element, BAD_CAST(str_ns));
  1460. if (nsptr != NULL) {
  1461. cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
  1462. }
  1463. if (str_ns) {efree(str_ns);}
  1464. if (cptype) {efree(cptype);}
  1465. }
  1466. trav = element->children;
  1467. if (trav != NULL && node_is_equal(trav, "annotation")) {
  1468. /* TODO: <annotation> support */
  1469. trav = trav->next;
  1470. }
  1471. if (trav != NULL) {
  1472. if (node_is_equal(trav,"simpleType")) {
  1473. if (ref != NULL) {
  1474. soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
  1475. } else if (type != NULL) {
  1476. soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
  1477. }
  1478. schema_simpleType(sdl, tns, trav, cur_type);
  1479. trav = trav->next;
  1480. } else if (node_is_equal(trav,"complexType")) {
  1481. if (ref != NULL) {
  1482. soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
  1483. } else if (type != NULL) {
  1484. soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
  1485. }
  1486. schema_complexType(sdl, tns, trav, cur_type);
  1487. trav = trav->next;
  1488. }
  1489. }
  1490. while (trav != NULL) {
  1491. if (node_is_equal(trav,"unique")) {
  1492. /* TODO: <unique> support */
  1493. } else if (node_is_equal(trav,"key")) {
  1494. /* TODO: <key> support */
  1495. } else if (node_is_equal(trav,"keyref")) {
  1496. /* TODO: <keyref> support */
  1497. } else {
  1498. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in element", trav->name);
  1499. }
  1500. trav = trav->next;
  1501. }
  1502. return TRUE;
  1503. }
  1504. /*
  1505. <attribute
  1506. default = string
  1507. fixed = string
  1508. form = (qualified | unqualified)
  1509. id = ID
  1510. name = NCName
  1511. ref = QName
  1512. type = QName
  1513. use = (optional | prohibited | required) : optional
  1514. {any attributes with non-schema namespace . . .}>
  1515. Content: (annotation?, (simpleType?))
  1516. </attribute>
  1517. */
  1518. static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx)
  1519. {
  1520. sdlAttributePtr newAttr;
  1521. xmlAttrPtr attr, name, ref = NULL, type = NULL;
  1522. xmlNodePtr trav;
  1523. name = get_attribute(attrType->properties, "name");
  1524. if (name == NULL) {
  1525. name = ref = get_attribute(attrType->properties, "ref");
  1526. }
  1527. if (name) {
  1528. HashTable *addHash;
  1529. smart_str key = {0};
  1530. newAttr = emalloc(sizeof(sdlAttribute));
  1531. memset(newAttr, 0, sizeof(sdlAttribute));
  1532. if (ref) {
  1533. char *attr_name, *ns;
  1534. xmlNsPtr nsptr;
  1535. parse_namespace(ref->children->content, &attr_name, &ns);
  1536. nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(ns));
  1537. if (nsptr != NULL) {
  1538. smart_str_appends(&key, (char*)nsptr->href);
  1539. smart_str_appendc(&key, ':');
  1540. newAttr->namens = estrdup((char*)nsptr->href);
  1541. }
  1542. smart_str_appends(&key, attr_name);
  1543. smart_str_0(&key);
  1544. newAttr->ref = estrdup(key.c);
  1545. if (attr_name) {efree(attr_name);}
  1546. if (ns) {efree(ns);}
  1547. } else {
  1548. xmlAttrPtr ns;
  1549. ns = get_attribute(attrType->properties, "targetNamespace");
  1550. if (ns == NULL) {
  1551. ns = tns;
  1552. }
  1553. if (ns != NULL) {
  1554. smart_str_appends(&key, (char*)ns->children->content);
  1555. smart_str_appendc(&key, ':');
  1556. newAttr->namens = estrdup((char*)ns->children->content);
  1557. }
  1558. smart_str_appends(&key, (char*)name->children->content);
  1559. smart_str_0(&key);
  1560. }
  1561. if (cur_type == NULL) {
  1562. addHash = ctx->attributes;
  1563. } else {
  1564. if (cur_type->attributes == NULL) {
  1565. cur_type->attributes = emalloc(sizeof(HashTable));
  1566. zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
  1567. }
  1568. addHash = cur_type->attributes;
  1569. }
  1570. if (zend_hash_add(addHash, key.c, key.len + 1, &newAttr, sizeof(sdlAttributePtr), NULL) != SUCCESS) {
  1571. soap_error1(E_ERROR, "Parsing Schema: attribute '%s' already defined", key.c);
  1572. }
  1573. smart_str_free(&key);
  1574. } else{
  1575. soap_error0(E_ERROR, "Parsing Schema: attribute has no 'name' nor 'ref' attributes");
  1576. }
  1577. /* type = QName */
  1578. type = get_attribute(attrType->properties, "type");
  1579. if (type) {
  1580. char *cptype, *str_ns;
  1581. xmlNsPtr nsptr;
  1582. if (ref != NULL) {
  1583. soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' and 'type' attributes");
  1584. }
  1585. parse_namespace(type->children->content, &cptype, &str_ns);
  1586. nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(str_ns));
  1587. if (nsptr != NULL) {
  1588. newAttr->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
  1589. }
  1590. if (str_ns) {efree(str_ns);}
  1591. if (cptype) {efree(cptype);}
  1592. }
  1593. attr = attrType->properties;
  1594. while (attr != NULL) {
  1595. if (attr_is_equal_ex(attr, "default", SCHEMA_NAMESPACE)) {
  1596. newAttr->def = estrdup((char*)attr->children->content);
  1597. } else if (attr_is_equal_ex(attr, "fixed", SCHEMA_NAMESPACE)) {
  1598. newAttr->fixed = estrdup((char*)attr->children->content);
  1599. } else if (attr_is_equal_ex(attr, "form", SCHEMA_NAMESPACE)) {
  1600. if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
  1601. newAttr->form = XSD_FORM_QUALIFIED;
  1602. } else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
  1603. newAttr->form = XSD_FORM_UNQUALIFIED;
  1604. } else {
  1605. newAttr->form = XSD_FORM_DEFAULT;
  1606. }
  1607. } else if (attr_is_equal_ex(attr, "id", SCHEMA_NAMESPACE)) {
  1608. /* skip */
  1609. } else if (attr_is_equal_ex(attr, "name", SCHEMA_NAMESPACE)) {
  1610. newAttr->name = estrdup((char*)attr->children->content);
  1611. } else if (attr_is_equal_ex(attr, "ref", SCHEMA_NAMESPACE)) {
  1612. /* already processed */
  1613. } else if (attr_is_equal_ex(attr, "type", SCHEMA_NAMESPACE)) {
  1614. /* already processed */
  1615. } else if (attr_is_equal_ex(attr, "use", SCHEMA_NAMESPACE)) {
  1616. if (strncmp((char*)attr->children->content, "prohibited", sizeof("prohibited")) == 0) {
  1617. newAttr->use = XSD_USE_PROHIBITED;
  1618. } else if (strncmp((char*)attr->children->content, "required", sizeof("required")) == 0) {
  1619. newAttr->use = XSD_USE_REQUIRED;
  1620. } else if (strncmp((char*)attr->children->content, "optional", sizeof("optional")) == 0) {
  1621. newAttr->use = XSD_USE_OPTIONAL;
  1622. } else {
  1623. newAttr->use = XSD_USE_DEFAULT;
  1624. }
  1625. } else {
  1626. xmlNsPtr nsPtr = attr_find_ns(attr);
  1627. if (strncmp((char*)nsPtr->href, SCHEMA_NAMESPACE, sizeof(SCHEMA_NAMESPACE))) {
  1628. smart_str key2 = {0};
  1629. sdlExtraAttributePtr ext;
  1630. xmlNsPtr nsptr;
  1631. char *value, *ns;
  1632. ext = emalloc(sizeof(sdlExtraAttribute));
  1633. memset(ext, 0, sizeof(sdlExtraAttribute));
  1634. parse_namespace(attr->children->content, &value, &ns);
  1635. nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
  1636. if (nsptr) {
  1637. ext->ns = estrdup((char*)nsptr->href);
  1638. ext->val = estrdup(value);
  1639. } else {
  1640. ext->val = estrdup((char*)attr->children->content);
  1641. }
  1642. if (ns) {efree(ns);}
  1643. efree(value);
  1644. if (!newAttr->extraAttributes) {
  1645. newAttr->extraAttributes = emalloc(sizeof(HashTable));
  1646. zend_hash_init(newAttr->extraAttributes, 0, NULL, delete_extra_attribute, 0);
  1647. }
  1648. smart_str_appends(&key2, (char*)nsPtr->href);
  1649. smart_str_appendc(&key2, ':');
  1650. smart_str_appends(&key2, (char*)attr->name);
  1651. smart_str_0(&key2);
  1652. zend_hash_add(newAttr->extraAttributes, key2.c, key2.len + 1, &ext, sizeof(sdlExtraAttributePtr), NULL);
  1653. smart_str_free(&key2);
  1654. }
  1655. }
  1656. attr = attr->next;
  1657. }
  1658. if (newAttr->form == XSD_FORM_DEFAULT) {
  1659. xmlNodePtr parent = attrType->parent;
  1660. while (parent) {
  1661. if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
  1662. xmlAttrPtr def;
  1663. def = get_attribute(parent->properties, "attributeFormDefault");
  1664. if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
  1665. newAttr->form = XSD_FORM_UNQUALIFIED;
  1666. } else {
  1667. newAttr->form = XSD_FORM_QUALIFIED;
  1668. }
  1669. break;
  1670. }
  1671. parent = parent->parent;
  1672. }
  1673. if (parent == NULL) {
  1674. newAttr->form = XSD_FORM_UNQUALIFIED;
  1675. }
  1676. }
  1677. trav = attrType->children;
  1678. if (trav != NULL && node_is_equal(trav, "annotation")) {
  1679. /* TODO: <annotation> support */
  1680. trav = trav->next;
  1681. }
  1682. if (trav != NULL) {
  1683. if (node_is_equal(trav,"simpleType")) {
  1684. sdlTypePtr dummy_type;
  1685. if (ref != NULL) {
  1686. soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' attribute and subtype");
  1687. } else if (type != NULL) {
  1688. soap_error0(E_ERROR, "Parsing Schema: attribute has both 'type' attribute and subtype");
  1689. }
  1690. dummy_type = emalloc(sizeof(sdlType));
  1691. memset(dummy_type, 0, sizeof(sdlType));
  1692. dummy_type->name = estrdup("anonymous");
  1693. dummy_type->namens = estrdup((char*)tns->children->content);
  1694. schema_simpleType(sdl, tns, trav, dummy_type);
  1695. newAttr->encode = dummy_type->encode;
  1696. delete_type(&dummy_type);
  1697. trav = trav->next;
  1698. }
  1699. }
  1700. if (trav != NULL) {
  1701. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attribute", trav->name);
  1702. }
  1703. return TRUE;
  1704. }
  1705. static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrGroup, sdlTypePtr cur_type, sdlCtx *ctx)
  1706. {
  1707. xmlNodePtr trav;
  1708. xmlAttrPtr name, ref = NULL;
  1709. name = get_attribute(attrGroup->properties, "name");
  1710. if (name == NULL) {
  1711. name = ref = get_attribute(attrGroup->properties, "ref");
  1712. }
  1713. if (name) {
  1714. if (cur_type == NULL) {
  1715. xmlAttrPtr ns;
  1716. sdlTypePtr newType;
  1717. smart_str key = {0};
  1718. ns = get_attribute(attrGroup->properties, "targetNamespace");
  1719. if (ns == NULL) {
  1720. ns = tns;
  1721. }
  1722. newType = emalloc(sizeof(sdlType));
  1723. memset(newType, 0, sizeof(sdlType));
  1724. newType->name = estrdup((char*)name->children->content);
  1725. newType->namens = estrdup((char*)ns->children->content);
  1726. smart_str_appends(&key, newType->namens);
  1727. smart_str_appendc(&key, ':');
  1728. smart_str_appends(&key, newType->name);
  1729. smart_str_0(&key);
  1730. if (zend_hash_add(ctx->attributeGroups, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
  1731. soap_error1(E_ERROR, "Parsing Schema: attributeGroup '%s' already defined", key.c);
  1732. }
  1733. cur_type = newType;
  1734. smart_str_free(&key);
  1735. } else if (ref) {
  1736. sdlAttributePtr newAttr;
  1737. char *group_name, *ns;
  1738. smart_str key = {0};
  1739. xmlNsPtr nsptr;
  1740. if (cur_type->attributes == NULL) {
  1741. cur_type->attributes = emalloc(sizeof(HashTable));
  1742. zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
  1743. }
  1744. newAttr = emalloc(sizeof(sdlAttribute));
  1745. memset(newAttr, 0, sizeof(sdlAttribute));
  1746. parse_namespace(ref->children->content, &group_name, &ns);
  1747. nsptr = xmlSearchNs(attrGroup->doc, attrGroup, BAD_CAST(ns));
  1748. if (nsptr != NULL) {
  1749. smart_str_appends(&key, (char*)nsptr->href);
  1750. smart_str_appendc(&key, ':');
  1751. }
  1752. smart_str_appends(&key, group_name);
  1753. smart_str_0(&key);
  1754. newAttr->ref = estrdup(key.c);
  1755. if (group_name) {efree(group_name);}
  1756. if (ns) {efree(ns);}
  1757. smart_str_free(&key);
  1758. zend_hash_next_index_insert(cur_type->attributes, &newAttr, sizeof(sdlAttributePtr), NULL);
  1759. cur_type = NULL;
  1760. }
  1761. } else{
  1762. soap_error0(E_ERROR, "Parsing Schema: attributeGroup has no 'name' nor 'ref' attributes");
  1763. }
  1764. trav = attrGroup->children;
  1765. if (trav != NULL && node_is_equal(trav, "annotation")) {
  1766. /* TODO: <annotation> support */
  1767. trav = trav->next;
  1768. }
  1769. while (trav != NULL) {
  1770. if (node_is_equal(trav,"attribute")) {
  1771. if (ref != NULL) {
  1772. soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
  1773. }
  1774. schema_attribute(sdl, tns, trav, cur_type, NULL);
  1775. } else if (node_is_equal(trav,"attributeGroup")) {
  1776. if (ref != NULL) {
  1777. soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
  1778. }
  1779. schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
  1780. } else if (node_is_equal(trav,"anyAttribute")) {
  1781. if (ref != NULL) {
  1782. soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
  1783. }
  1784. /* TODO: <anyAttribute> support */
  1785. trav = trav->next;
  1786. break;
  1787. } else {
  1788. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
  1789. }
  1790. trav = trav->next;
  1791. }
  1792. if (trav != NULL) {
  1793. soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
  1794. }
  1795. return TRUE;
  1796. }
  1797. static void copy_extra_attribute(void *attribute)
  1798. {
  1799. sdlExtraAttributePtr *attr = (sdlExtraAttributePtr*)attribute;
  1800. sdlExtraAttributePtr new_attr;
  1801. new_attr = emalloc(sizeof(sdlExtraAttribute));
  1802. memcpy(new_attr, *attr, sizeof(sdlExtraAttribute));
  1803. *attr = new_attr;
  1804. if (new_attr->ns) {
  1805. new_attr->ns = estrdup(new_attr->ns);
  1806. }
  1807. if (new_attr->val) {
  1808. new_attr->val = estrdup(new_attr->val);
  1809. }
  1810. }
  1811. static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
  1812. {
  1813. sdlAttributePtr *tmp;
  1814. if (attr->ref != NULL) {
  1815. if (ctx->attributes != NULL) {
  1816. if (zend_hash_find(ctx->attributes, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
  1817. schema_attribute_fixup(ctx, *tmp);
  1818. if ((*tmp)->name != NULL && attr->name == NULL) {
  1819. attr->name = estrdup((*tmp)->name);
  1820. }
  1821. if ((*tmp)->namens != NULL && attr->namens == NULL) {
  1822. attr->namens = estrdup((*tmp)->namens);
  1823. }
  1824. if ((*tmp)->def != NULL && attr->def == NULL) {
  1825. attr->def = estrdup((*tmp)->def);
  1826. }
  1827. if ((*tmp)->fixed != NULL && attr->fixed == NULL) {
  1828. attr->fixed = estrdup((*tmp)->fixed);
  1829. }
  1830. if (attr->form == XSD_FORM_DEFAULT) {
  1831. attr->form = (*tmp)->form;
  1832. }
  1833. if (attr->use == XSD_USE_DEFAULT) {
  1834. attr->use = (*tmp)->use;
  1835. }
  1836. if ((*tmp)->extraAttributes != NULL) {
  1837. xmlNodePtr node;
  1838. attr->extraAttributes = emalloc(sizeof(HashTable));
  1839. zend_hash_init(attr->extraAttributes, zend_hash_num_elements((*tmp)->extraAttributes), NULL, delete_extra_attribute, 0);
  1840. zend_hash_copy(attr->extraAttributes, (*tmp)->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
  1841. }
  1842. attr->encode = (*tmp)->encode;
  1843. }
  1844. }
  1845. if (attr->name == NULL && attr->ref != NULL) {
  1846. char *name = strrchr(attr->ref, ':');
  1847. if (name) {
  1848. attr->name = estrdup(name+1);
  1849. } else{
  1850. attr->name = estrdup(attr->ref);
  1851. }
  1852. }
  1853. efree(attr->ref);
  1854. attr->ref = NULL;
  1855. }
  1856. }
  1857. static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashTable *ht)
  1858. {
  1859. sdlTypePtr *tmp;
  1860. sdlAttributePtr *tmp_attr;
  1861. if (attr->ref != NULL) {
  1862. if (ctx->attributeGroups != NULL) {
  1863. if (zend_hash_find(ctx->attributeGroups, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
  1864. if ((*tmp)->attributes) {
  1865. zend_hash_internal_pointer_reset((*tmp)->attributes);
  1866. while (zend_hash_get_current_data((*tmp)->attributes,(void**)&tmp_attr) == SUCCESS) {
  1867. if (zend_hash_get_current_key_type((*tmp)->attributes) == HASH_KEY_IS_STRING) {
  1868. char* key;
  1869. uint key_len;
  1870. sdlAttributePtr newAttr;
  1871. schema_attribute_fixup(ctx,*tmp_attr);
  1872. newAttr = emalloc(sizeof(sdlAttribute));
  1873. memcpy(newAttr, *tmp_attr, sizeof(sdlAttribute));
  1874. if (newAttr->def) {newAttr->def = estrdup(newAttr->def);}
  1875. if (newAttr->fixed) {newAttr->fixed = estrdup(newAttr->fixed);}
  1876. if (newAttr->namens) {newAttr->namens = estrdup(newAttr->namens);}
  1877. if (newAttr->name) {newAttr->name = estrdup(newAttr->name);}
  1878. if (newAttr->extraAttributes) {
  1879. xmlNodePtr node;
  1880. HashTable *ht = emalloc(sizeof(HashTable));
  1881. zend_hash_init(ht, zend_hash_num_elements(newAttr->extraAttributes), NULL, delete_extra_attribute, 0);
  1882. zend_hash_copy(ht, newAttr->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
  1883. newAttr->extraAttributes = ht;
  1884. }
  1885. zend_hash_get_current_key_ex((*tmp)->attributes, &key, &key_len, NULL, 0, NULL);
  1886. zend_hash_add(ht, key, key_len, &newAttr, sizeof(sdlAttributePtr), NULL);
  1887. zend_hash_move_forward((*tmp)->attributes);
  1888. } else {
  1889. ulong index;
  1890. schema_attributegroup_fixup(ctx,*tmp_attr, ht);
  1891. zend_hash_get_current_key((*tmp)->attributes, NULL, &index, 0);
  1892. zend_hash_index_del((*tmp)->attributes, index);
  1893. }
  1894. }
  1895. }
  1896. }
  1897. }
  1898. efree(attr->ref);
  1899. attr->ref = NULL;
  1900. }
  1901. }
  1902. static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
  1903. {
  1904. switch (model->kind) {
  1905. case XSD_CONTENT_GROUP_REF: {
  1906. sdlTypePtr *tmp;
  1907. if (ctx->sdl->groups && zend_hash_find(ctx->sdl->groups, model->u.group_ref, strlen(model->u.group_ref)+1, (void**)&tmp) == SUCCESS) {
  1908. schema_type_fixup(ctx,*tmp);
  1909. efree(model->u.group_ref);
  1910. model->kind = XSD_CONTENT_GROUP;
  1911. model->u.group = (*tmp);
  1912. } else {
  1913. soap_error0(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute");
  1914. }
  1915. break;
  1916. }
  1917. case XSD_CONTENT_CHOICE: {
  1918. if (model->max_occurs != 1) {
  1919. HashPosition pos;
  1920. sdlContentModelPtr *tmp;
  1921. zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
  1922. while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
  1923. (*tmp)->min_occurs = 0;
  1924. (*tmp)->max_occurs = model->max_occurs;
  1925. zend_hash_move_forward_ex(model->u.content, &pos);
  1926. }
  1927. model->kind = XSD_CONTENT_ALL;
  1928. model->min_occurs = 1;
  1929. model->max_occurs = 1;
  1930. }
  1931. }
  1932. case XSD_CONTENT_SEQUENCE:
  1933. case XSD_CONTENT_ALL: {
  1934. sdlContentModelPtr *tmp;
  1935. zend_hash_internal_pointer_reset(model->u.content);
  1936. while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
  1937. schema_content_model_fixup(ctx, *tmp);
  1938. zend_hash_move_forward(model->u.content);
  1939. }
  1940. break;
  1941. }
  1942. default:
  1943. break;
  1944. }
  1945. }
  1946. static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
  1947. {
  1948. sdlTypePtr *tmp;
  1949. sdlAttributePtr *attr;
  1950. if (type->ref != NULL) {
  1951. if (ctx->sdl->elements != NULL) {
  1952. if (zend_hash_find(ctx->sdl->elements, type->ref, strlen(type->ref)+1, (void**)&tmp) == SUCCESS) {
  1953. type->kind = (*tmp)->kind;
  1954. type->encode = (*tmp)->encode;
  1955. if ((*tmp)->nillable) {
  1956. type->nillable = 1;
  1957. }
  1958. if ((*tmp)->fixed) {
  1959. type->fixed = estrdup((*tmp)->fixed);
  1960. }
  1961. if ((*tmp)->def) {
  1962. type->def = estrdup((*tmp)->def);
  1963. }
  1964. type->form = (*tmp)->form;
  1965. } else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
  1966. type->encode = get_conversion(XSD_ANYXML);
  1967. } else {
  1968. soap_error0(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute");
  1969. }
  1970. }
  1971. efree(type->ref);
  1972. type->ref = NULL;
  1973. }
  1974. if (type->elements) {
  1975. zend_hash_internal_pointer_reset(type->elements);
  1976. while (zend_hash_get_current_data(type->elements,(void**)&tmp) == SUCCESS) {
  1977. schema_type_fixup(ctx,*tmp);
  1978. zend_hash_move_forward(type->elements);
  1979. }
  1980. }
  1981. if (type->model) {
  1982. schema_content_model_fixup(ctx, type->model);
  1983. }
  1984. if (type->attributes) {
  1985. zend_hash_internal_pointer_reset(type->attributes);
  1986. while (zend_hash_get_current_data(type->attributes,(void**)&attr) == SUCCESS) {
  1987. if (zend_hash_get_current_key_type(type->attributes) == HASH_KEY_IS_STRING) {
  1988. schema_attribute_fixup(ctx,*attr);
  1989. zend_hash_move_forward(type->attributes);
  1990. } else {
  1991. ulong index;
  1992. schema_attributegroup_fixup(ctx,*attr,type->attributes);
  1993. zend_hash_get_current_key(type->attributes, NULL, &index, 0);
  1994. zend_hash_index_del(type->attributes, index);
  1995. }
  1996. }
  1997. }
  1998. }
  1999. void schema_pass2(sdlCtx *ctx)
  2000. {
  2001. sdlPtr sdl = ctx->sdl;
  2002. sdlAttributePtr *attr;
  2003. sdlTypePtr *type;
  2004. if (ctx->attributes) {
  2005. zend_hash_internal_pointer_reset(ctx->attributes);
  2006. while (zend_hash_get_current_data(ctx->attributes,(void**)&attr) == SUCCESS) {
  2007. schema_attribute_fixup(ctx,*attr);
  2008. zend_hash_move_forward(ctx->attributes);
  2009. }
  2010. }
  2011. if (ctx->attributeGroups) {
  2012. zend_hash_internal_pointer_reset(ctx->attributeGroups);
  2013. while (zend_hash_get_current_data(ctx->attributeGroups,(void**)&type) == SUCCESS) {
  2014. schema_type_fixup(ctx,*type);
  2015. zend_hash_move_forward(ctx->attributeGroups);
  2016. }
  2017. }
  2018. if (sdl->elements) {
  2019. zend_hash_internal_pointer_reset(sdl->elements);
  2020. while (zend_hash_get_current_data(sdl->elements,(void**)&type) == SUCCESS) {
  2021. schema_type_fixup(ctx,*type);
  2022. zend_hash_move_forward(sdl->elements);
  2023. }
  2024. }
  2025. if (sdl->groups) {
  2026. zend_hash_internal_pointer_reset(sdl->groups);
  2027. while (zend_hash_get_current_data(sdl->groups,(void**)&type) == SUCCESS) {
  2028. schema_type_fixup(ctx,*type);
  2029. zend_hash_move_forward(sdl->groups);
  2030. }
  2031. }
  2032. if (sdl->types) {
  2033. zend_hash_internal_pointer_reset(sdl->types);
  2034. while (zend_hash_get_current_data(sdl->types,(void**)&type) == SUCCESS) {
  2035. schema_type_fixup(ctx,*type);
  2036. zend_hash_move_forward(sdl->types);
  2037. }
  2038. }
  2039. if (ctx->attributes) {
  2040. zend_hash_destroy(ctx->attributes);
  2041. efree(ctx->attributes);
  2042. }
  2043. if (ctx->attributeGroups) {
  2044. zend_hash_destroy(ctx->attributeGroups);
  2045. efree(ctx->attributeGroups);
  2046. }
  2047. }
  2048. void delete_model(void *handle)
  2049. {
  2050. sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
  2051. switch (tmp->kind) {
  2052. case XSD_CONTENT_ELEMENT:
  2053. case XSD_CONTENT_GROUP:
  2054. break;
  2055. case XSD_CONTENT_SEQUENCE:
  2056. case XSD_CONTENT_ALL:
  2057. case XSD_CONTENT_CHOICE:
  2058. zend_hash_destroy(tmp->u.content);
  2059. efree(tmp->u.content);
  2060. break;
  2061. case XSD_CONTENT_GROUP_REF:
  2062. efree(tmp->u.group_ref);
  2063. break;
  2064. default:
  2065. break;
  2066. }
  2067. efree(tmp);
  2068. }
  2069. void delete_model_persistent(void *handle)
  2070. {
  2071. sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
  2072. switch (tmp->kind) {
  2073. case XSD_CONTENT_ELEMENT:
  2074. case XSD_CONTENT_GROUP:
  2075. break;
  2076. case XSD_CONTENT_SEQUENCE:
  2077. case XSD_CONTENT_ALL:
  2078. case XSD_CONTENT_CHOICE:
  2079. zend_hash_destroy(tmp->u.content);
  2080. free(tmp->u.content);
  2081. break;
  2082. case XSD_CONTENT_GROUP_REF:
  2083. free(tmp->u.group_ref);
  2084. break;
  2085. default:
  2086. break;
  2087. }
  2088. free(tmp);
  2089. }
  2090. void delete_type(void *data)
  2091. {
  2092. sdlTypePtr type = *((sdlTypePtr*)data);
  2093. if (type->name) {
  2094. efree(type->name);
  2095. }
  2096. if (type->namens) {
  2097. efree(type->namens);
  2098. }
  2099. if (type->def) {
  2100. efree(type->def);
  2101. }
  2102. if (type->fixed) {
  2103. efree(type->fixed);
  2104. }
  2105. if (type->elements) {
  2106. zend_hash_destroy(type->elements);
  2107. efree(type->elements);
  2108. }
  2109. if (type->attributes) {
  2110. zend_hash_destroy(type->attributes);
  2111. efree(type->attributes);
  2112. }
  2113. if (type->model) {
  2114. delete_model((void**)&type->model);
  2115. }
  2116. if (type->restrictions) {
  2117. delete_restriction_var_int(&type->restrictions->minExclusive);
  2118. delete_restriction_var_int(&type->restrictions->minInclusive);
  2119. delete_restriction_var_int(&type->restrictions->maxExclusive);
  2120. delete_restriction_var_int(&type->restrictions->maxInclusive);
  2121. delete_restriction_var_int(&type->restrictions->totalDigits);
  2122. delete_restriction_var_int(&type->restrictions->fractionDigits);
  2123. delete_restriction_var_int(&type->restrictions->length);
  2124. delete_restriction_var_int(&type->restrictions->minLength);
  2125. delete_restriction_var_int(&type->restrictions->maxLength);
  2126. delete_restriction_var_char(&type->restrictions->whiteSpace);
  2127. delete_restriction_var_char(&type->restrictions->pattern);
  2128. if (type->restrictions->enumeration) {
  2129. zend_hash_destroy(type->restrictions->enumeration);
  2130. efree(type->restrictions->enumeration);
  2131. }
  2132. efree(type->restrictions);
  2133. }
  2134. efree(type);
  2135. }
  2136. void delete_type_persistent(void *data)
  2137. {
  2138. sdlTypePtr type = *((sdlTypePtr*)data);
  2139. if (type->name) {
  2140. free(type->name);
  2141. }
  2142. if (type->namens) {
  2143. free(type->namens);
  2144. }
  2145. if (type->def) {
  2146. free(type->def);
  2147. }
  2148. if (type->fixed) {
  2149. free(type->fixed);
  2150. }
  2151. if (type->elements) {
  2152. zend_hash_destroy(type->elements);
  2153. free(type->elements);
  2154. }
  2155. if (type->attributes) {
  2156. zend_hash_destroy(type->attributes);
  2157. free(type->attributes);
  2158. }
  2159. if (type->model) {
  2160. delete_model_persistent((void**)&type->model);
  2161. }
  2162. if (type->restrictions) {
  2163. delete_restriction_var_int_persistent(&type->restrictions->minExclusive);
  2164. delete_restriction_var_int_persistent(&type->restrictions->minInclusive);
  2165. delete_restriction_var_int_persistent(&type->restrictions->maxExclusive);
  2166. delete_restriction_var_int_persistent(&type->restrictions->maxInclusive);
  2167. delete_restriction_var_int_persistent(&type->restrictions->totalDigits);
  2168. delete_restriction_var_int_persistent(&type->restrictions->fractionDigits);
  2169. delete_restriction_var_int_persistent(&type->restrictions->length);
  2170. delete_restriction_var_int_persistent(&type->restrictions->minLength);
  2171. delete_restriction_var_int_persistent(&type->restrictions->maxLength);
  2172. delete_restriction_var_char_persistent(&type->restrictions->whiteSpace);
  2173. delete_restriction_var_char_persistent(&type->restrictions->pattern);
  2174. if (type->restrictions->enumeration) {
  2175. zend_hash_destroy(type->restrictions->enumeration);
  2176. free(type->restrictions->enumeration);
  2177. }
  2178. free(type->restrictions);
  2179. }
  2180. free(type);
  2181. }
  2182. void delete_extra_attribute(void *attribute)
  2183. {
  2184. sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
  2185. if (attr->ns) {
  2186. efree(attr->ns);
  2187. }
  2188. if (attr->val) {
  2189. efree(attr->val);
  2190. }
  2191. efree(attr);
  2192. }
  2193. void delete_extra_attribute_persistent(void *attribute)
  2194. {
  2195. sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
  2196. if (attr->ns) {
  2197. free(attr->ns);
  2198. }
  2199. if (attr->val) {
  2200. free(attr->val);
  2201. }
  2202. free(attr);
  2203. }
  2204. void delete_attribute(void *attribute)
  2205. {
  2206. sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
  2207. if (attr->def) {
  2208. efree(attr->def);
  2209. }
  2210. if (attr->fixed) {
  2211. efree(attr->fixed);
  2212. }
  2213. if (attr->name) {
  2214. efree(attr->name);
  2215. }
  2216. if (attr->namens) {
  2217. efree(attr->namens);
  2218. }
  2219. if (attr->ref) {
  2220. efree(attr->ref);
  2221. }
  2222. if (attr->extraAttributes) {
  2223. zend_hash_destroy(attr->extraAttributes);
  2224. efree(attr->extraAttributes);
  2225. }
  2226. efree(attr);
  2227. }
  2228. void delete_attribute_persistent(void *attribute)
  2229. {
  2230. sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
  2231. if (attr->def) {
  2232. free(attr->def);
  2233. }
  2234. if (attr->fixed) {
  2235. free(attr->fixed);
  2236. }
  2237. if (attr->name) {
  2238. free(attr->name);
  2239. }
  2240. if (attr->namens) {
  2241. free(attr->namens);
  2242. }
  2243. if (attr->ref) {
  2244. free(attr->ref);
  2245. }
  2246. if (attr->extraAttributes) {
  2247. zend_hash_destroy(attr->extraAttributes);
  2248. free(attr->extraAttributes);
  2249. }
  2250. free(attr);
  2251. }
  2252. void delete_restriction_var_int(void *rvi)
  2253. {
  2254. sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
  2255. if (ptr) {
  2256. efree(ptr);
  2257. }
  2258. }
  2259. void delete_restriction_var_int_persistent(void *rvi)
  2260. {
  2261. sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
  2262. if (ptr) {
  2263. free(ptr);
  2264. }
  2265. }
  2266. void delete_restriction_var_char(void *srvc)
  2267. {
  2268. sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
  2269. if (ptr) {
  2270. if (ptr->value) {
  2271. efree(ptr->value);
  2272. }
  2273. efree(ptr);
  2274. }
  2275. }
  2276. void delete_restriction_var_char_persistent(void *srvc)
  2277. {
  2278. sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
  2279. if (ptr) {
  2280. if (ptr->value) {
  2281. free(ptr->value);
  2282. }
  2283. free(ptr);
  2284. }
  2285. }