ObjFW  Check-in [2d28a0fda4]

Overview
Comment:Handle <!DOCTYPE> in OFXMLParser.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2d28a0fda46ec5722b782407b0cd96ee1fa85342b94f3dc9d16facb9f0b614ef
User & Date: js on 2010-11-14 23:49:24
Other Links: manifest | tags
Context
2010-11-15
08:21
Reduce the number of states and correctly handle \t in OFXMLParser. check-in: e23674756b user: js tags: trunk
2010-11-14
23:49
Handle <!DOCTYPE> in OFXMLParser. check-in: 2d28a0fda4 user: js tags: trunk
2010-11-13
21:57
Add -[description] for OFObject, OFString, OFArray and OFDictionary. check-in: 9b50b86632 user: js tags: trunk
Changes

Modified src/OFXMLParser.h from [b18421a980] to [76fd487c9d].

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
		OF_XMLPARSER_IN_CLOSE_TAG_NAME,
		OF_XMLPARSER_IN_TAG,
		OF_XMLPARSER_IN_ATTR_NAME,
		OF_XMLPARSER_EXPECT_DELIM,
		OF_XMLPARSER_IN_ATTR_VALUE,
		OF_XMLPARSER_EXPECT_CLOSE,
		OF_XMLPARSER_EXPECT_SPACE_OR_CLOSE,
		OF_XMLPARSER_IN_CDATA_OR_COMMENT,
		OF_XMLPARSER_IN_CDATA_OPENING_1,
		OF_XMLPARSER_IN_CDATA_OPENING_2,
		OF_XMLPARSER_IN_CDATA_OPENING_3,
		OF_XMLPARSER_IN_CDATA_OPENING_4,
		OF_XMLPARSER_IN_CDATA_OPENING_5,
		OF_XMLPARSER_IN_CDATA_OPENING_6,
		OF_XMLPARSER_IN_CDATA_1,
		OF_XMLPARSER_IN_CDATA_2,
		OF_XMLPARSER_IN_CDATA_3,
		OF_XMLPARSER_IN_COMMENT_OPENING,
		OF_XMLPARSER_IN_COMMENT_1,
		OF_XMLPARSER_IN_COMMENT_2,
		OF_XMLPARSER_IN_COMMENT_3,

		OF_XMLPARSER_NUM_STATES
	} state;
	OFMutableString *cache;
	OFString *name;
	OFString *prefix;
	OFMutableArray *namespaces;
	OFMutableArray *attrs;
	OFString *attrName;
	OFString *attrPrefix;
	char delim;
	OFMutableArray *previous;
#ifdef OF_HAVE_BLOCKS
	of_xml_parser_element_start_block_t elementStartHandler;
	of_xml_parser_element_end_block_t elementEndHandler;
	of_xml_parser_string_block_t charactersHandler;
	of_xml_parser_string_block_t CDATAHandler;
	of_xml_parser_string_block_t commentHandler;
	of_xml_parser_unknown_entity_block_t unknownEntityHandler;
#endif

}

#ifdef OF_HAVE_PROPERTIES
@property (retain) id <OFXMLParserDelegate> delegate;
# ifdef OF_HAVE_BLOCKS
@property (copy) of_xml_parser_element_start_block_t elementStartHandler;
@property (copy) of_xml_parser_element_end_block_t elementEndHandler;







|













>



















>







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
		OF_XMLPARSER_IN_CLOSE_TAG_NAME,
		OF_XMLPARSER_IN_TAG,
		OF_XMLPARSER_IN_ATTR_NAME,
		OF_XMLPARSER_EXPECT_DELIM,
		OF_XMLPARSER_IN_ATTR_VALUE,
		OF_XMLPARSER_EXPECT_CLOSE,
		OF_XMLPARSER_EXPECT_SPACE_OR_CLOSE,
		OF_XMLPARSER_IN_EXCLAMATIONMARK,
		OF_XMLPARSER_IN_CDATA_OPENING_1,
		OF_XMLPARSER_IN_CDATA_OPENING_2,
		OF_XMLPARSER_IN_CDATA_OPENING_3,
		OF_XMLPARSER_IN_CDATA_OPENING_4,
		OF_XMLPARSER_IN_CDATA_OPENING_5,
		OF_XMLPARSER_IN_CDATA_OPENING_6,
		OF_XMLPARSER_IN_CDATA_1,
		OF_XMLPARSER_IN_CDATA_2,
		OF_XMLPARSER_IN_CDATA_3,
		OF_XMLPARSER_IN_COMMENT_OPENING,
		OF_XMLPARSER_IN_COMMENT_1,
		OF_XMLPARSER_IN_COMMENT_2,
		OF_XMLPARSER_IN_COMMENT_3,
		OF_XMLPARSER_IN_DOCTYPE,
		OF_XMLPARSER_NUM_STATES
	} state;
	OFMutableString *cache;
	OFString *name;
	OFString *prefix;
	OFMutableArray *namespaces;
	OFMutableArray *attrs;
	OFString *attrName;
	OFString *attrPrefix;
	char delim;
	OFMutableArray *previous;
#ifdef OF_HAVE_BLOCKS
	of_xml_parser_element_start_block_t elementStartHandler;
	of_xml_parser_element_end_block_t elementEndHandler;
	of_xml_parser_string_block_t charactersHandler;
	of_xml_parser_string_block_t CDATAHandler;
	of_xml_parser_string_block_t commentHandler;
	of_xml_parser_unknown_entity_block_t unknownEntityHandler;
#endif
	size_t level;
}

#ifdef OF_HAVE_PROPERTIES
@property (retain) id <OFXMLParserDelegate> delegate;
# ifdef OF_HAVE_BLOCKS
@property (copy) of_xml_parser_element_start_block_t elementStartHandler;
@property (copy) of_xml_parser_element_end_block_t elementEndHandler;

Modified src/OFXMLParser.m from [686f9660a5] to [bafad23096].

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
		@selector(_parseInCloseTagNameWithBuffer:i:last:),
		@selector(_parseInTagWithBuffer:i:last:),
		@selector(_parseInAttributeNameWithBuffer:i:last:),
		@selector(_parseExpectDelimiterWithBuffer:i:last:),
		@selector(_parseInAttributeValueWithBuffer:i:last:),
		@selector(_parseExpectCloseWithBuffer:i:last:),
		@selector(_parseExpectSpaceOrCloseWithBuffer:i:last:),
		@selector(_parseInCDATAOrCommentWithBuffer:i:last:),
		@selector(_parseInCDATAOpening1WithBuffer:i:last:),
		@selector(_parseInCDATAOpening2WithBuffer:i:last:),
		@selector(_parseInCDATAOpening3WithBuffer:i:last:),
		@selector(_parseInCDATAOpening4WithBuffer:i:last:),
		@selector(_parseInCDATAOpening5WithBuffer:i:last:),
		@selector(_parseInCDATAOpening6WithBuffer:i:last:),
		@selector(_parseInCDATA1WithBuffer:i:last:),
		@selector(_parseInCDATA2WithBuffer:i:last:),
		@selector(_parseInCDATA3WithBuffer:i:last:),
		@selector(_parseInCommentOpeningWithBuffer:i:last:),
		@selector(_parseInComment1WithBuffer:i:last:),
		@selector(_parseInComment2WithBuffer:i:last:),
		@selector(_parseInComment3WithBuffer:i:last:)

	};
	memcpy(selectors, sels, sizeof(sels));

	for (i = 0; i < OF_XMLPARSER_NUM_STATES; i++) {
		if (![self instancesRespondToSelector: selectors[i]])
			@throw [OFInitializationFailedException
			    newWithClass: self];







|












|
>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
		@selector(_parseInCloseTagNameWithBuffer:i:last:),
		@selector(_parseInTagWithBuffer:i:last:),
		@selector(_parseInAttributeNameWithBuffer:i:last:),
		@selector(_parseExpectDelimiterWithBuffer:i:last:),
		@selector(_parseInAttributeValueWithBuffer:i:last:),
		@selector(_parseExpectCloseWithBuffer:i:last:),
		@selector(_parseExpectSpaceOrCloseWithBuffer:i:last:),
		@selector(_parseInExclamationMarkWithBuffer:i:last:),
		@selector(_parseInCDATAOpening1WithBuffer:i:last:),
		@selector(_parseInCDATAOpening2WithBuffer:i:last:),
		@selector(_parseInCDATAOpening3WithBuffer:i:last:),
		@selector(_parseInCDATAOpening4WithBuffer:i:last:),
		@selector(_parseInCDATAOpening5WithBuffer:i:last:),
		@selector(_parseInCDATAOpening6WithBuffer:i:last:),
		@selector(_parseInCDATA1WithBuffer:i:last:),
		@selector(_parseInCDATA2WithBuffer:i:last:),
		@selector(_parseInCDATA3WithBuffer:i:last:),
		@selector(_parseInCommentOpeningWithBuffer:i:last:),
		@selector(_parseInComment1WithBuffer:i:last:),
		@selector(_parseInComment2WithBuffer:i:last:),
		@selector(_parseInComment3WithBuffer:i:last:),
		@selector(_parseInDoctypeWithBuffer:i:last:),
	};
	memcpy(selectors, sels, sizeof(sels));

	for (i = 0; i < OF_XMLPARSER_NUM_STATES; i++) {
		if (![self instancesRespondToSelector: selectors[i]])
			@throw [OFInitializationFailedException
			    newWithClass: self];
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
			break;
		case '/':
			*last = *i + 1;
			state = OF_XMLPARSER_IN_CLOSE_TAG_NAME;
			break;
		case '!':
			*last = *i + 1;
			state = OF_XMLPARSER_IN_CDATA_OR_COMMENT;
			break;
		default:
			state = OF_XMLPARSER_IN_TAG_NAME;
			(*i)--;
			break;
	}
}







|







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
			break;
		case '/':
			*last = *i + 1;
			state = OF_XMLPARSER_IN_CLOSE_TAG_NAME;
			break;
		case '!':
			*last = *i + 1;
			state = OF_XMLPARSER_IN_EXCLAMATIONMARK;
			break;
		default:
			state = OF_XMLPARSER_IN_TAG_NAME;
			(*i)--;
			break;
	}
}
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726



727
728
729
730
731
732
733
734
	if (buf[*i] == '>') {
		*last = *i + 1;
		state = OF_XMLPARSER_OUTSIDE_TAG;
	} else if (buf[*i] != ' ' && buf[*i] != '\n' && buf[*i] != '\r')
		@throw [OFMalformedXMLException newWithClass: isa];
}

/* CDATA or comment */
- (void)_parseInCDATAOrCommentWithBuffer: (const char*)buf
				       i: (size_t*)i
				    last: (size_t*)last
{
	if (buf[*i] == '-')
		state = OF_XMLPARSER_IN_COMMENT_OPENING;
	else if (buf[*i] == '[')
		state = OF_XMLPARSER_IN_CDATA_OPENING_1;



	else
		@throw [OFMalformedXMLException newWithClass: isa];

	*last = *i + 1;
}

/* CDATA */
- (void)_parseInCDATAOpening1WithBuffer: (const char*)buf







|
|
|
|





>
>
>
|







712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
	if (buf[*i] == '>') {
		*last = *i + 1;
		state = OF_XMLPARSER_OUTSIDE_TAG;
	} else if (buf[*i] != ' ' && buf[*i] != '\n' && buf[*i] != '\r')
		@throw [OFMalformedXMLException newWithClass: isa];
}

/* In <! */
- (void)_parseInExclamationMarkWithBuffer: (const char*)buf
					i: (size_t*)i
				     last: (size_t*)last
{
	if (buf[*i] == '-')
		state = OF_XMLPARSER_IN_COMMENT_OPENING;
	else if (buf[*i] == '[')
		state = OF_XMLPARSER_IN_CDATA_OPENING_1;
	else if (buf[*i] == 'D') {
		state = OF_XMLPARSER_IN_DOCTYPE;
		level = 0;
	} else
		@throw [OFMalformedXMLException newWithClass: isa];

	*last = *i + 1;
}

/* CDATA */
- (void)_parseInCDATAOpening1WithBuffer: (const char*)buf
925
926
927
928
929
930
931























932
933
934
935
936
937
938
	[pool release];

	[cache setToCString: ""];

	*last = *i + 1;
	state = OF_XMLPARSER_OUTSIDE_TAG;
}
























-	   (OFString*)string: (OFString*)string
  containsUnknownEntityNamed: (OFString*)entity
{
#ifdef OF_HAVE_BLOCKS
	if (unknownEntityHandler != NULL)
		return unknownEntityHandler(self, entity);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
	[pool release];

	[cache setToCString: ""];

	*last = *i + 1;
	state = OF_XMLPARSER_OUTSIDE_TAG;
}

/* In <!DOCTYPE ...> */
- (void)_parseInDoctypeWithBuffer: (const char*)buf
				i: (size_t*)i
			     last: (size_t*)last
{
	if ((level < 6 && buf[*i] != "OCTYPE"[level]) ||
	    (level == 6 && buf[*i] != ' ' && buf[*i] != '\t' &&
	    buf[*i] != '\n' && buf[*i] != '\r'))
		@throw [OFMalformedXMLException newWithClass: isa];

	if (level < 7 || buf[*i] == '<')
		level++;

	if (buf[*i] == '>') {
		if (level == 7)
			state = OF_XMLPARSER_OUTSIDE_TAG;
		else
			level--;
	}

	*last = *i + 1;
}

-	   (OFString*)string: (OFString*)string
  containsUnknownEntityNamed: (OFString*)entity
{
#ifdef OF_HAVE_BLOCKS
	if (unknownEntityHandler != NULL)
		return unknownEntityHandler(self, entity);

Modified tests/OFXMLParserTests.m from [a5fed6b08d] to [da9c2e0fdf].

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
	return nil;
}

- (void)XMLParserTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFXMLParser *parser;
	const char *str = "<?xml version='1.0'?><root>\n"
	    " <![CDATA[f<oo]]><bar/>\n"
	    " <foobar xmlns='urn:objfw:test:foobar'>\n"
	    "  <qux xmlns:foo='urn:objfw:test:foo'>\n"
	    "   <foo:bla foo:bla='&#x62;&#x6c;&#x61;' blafoo='foo'>\n"
	    "    <blup foo:qux='asd' quxqux='test'/>\n"
	    "    <bla:bla\r\rxmlns:bla=\"urn:objfw:test:bla\" qux='qux'\r\n"
	    "     bla:foo='blafoo'/>\n"







|







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
	return nil;
}

- (void)XMLParserTests
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFXMLParser *parser;
	const char *str = "<?xml version='1.0'?><!DOCTYPE <<><<>>>><root>\n"
	    " <![CDATA[f<oo]]><bar/>\n"
	    " <foobar xmlns='urn:objfw:test:foobar'>\n"
	    "  <qux xmlns:foo='urn:objfw:test:foo'>\n"
	    "   <foo:bla foo:bla='&#x62;&#x6c;&#x61;' blafoo='foo'>\n"
	    "    <blup foo:qux='asd' quxqux='test'/>\n"
	    "    <bla:bla\r\rxmlns:bla=\"urn:objfw:test:bla\" qux='qux'\r\n"
	    "     bla:foo='blafoo'/>\n"