1 // =================================================================================================
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // All Rights Reserved.
4 //
5 // NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
6 // of the Adobe license agreement accompanying it.
7 // =================================================================================================
8 
9 #include "XMP_Environment.h"	// ! Must be the first #include!
10 #include "XMLParserAdapter.hpp"
11 
12 #include <map>
13 #include <cstring>
14 #include <cstdio>
15 
16 // ! Can't include XMP..._Impl.hpp - used by both Core and Files.
17 #define XMP_LitNMatch(s,l,n)	(std::strncmp((s),(l),(n)) == 0)
18 
19 #if XMP_WinBuild
20 #ifdef _MSC_VER
21 	#define snprintf _snprintf
22 	#pragma warning ( disable : 4996 )	// snprintf is safe
23 #endif
24 #endif
25 
26 // =================================================================================================
27 
28 #if 0	// Pattern for iterating over the children or attributes:
29 	for ( size_t xxNum = 0, xxLim = _node_->_offspring_->size(); xxNum < xxLim; ++xxNum ) {
30 		const XML_NodePtr _curr_ = _node_->_offspring_[xxNum];
31 	}
32 #endif
33 
34 // =================================================================================================
35 // XML_Node::IsWhitespaceNode
36 //===========================
37 
IsWhitespaceNode() const38 bool XML_Node::IsWhitespaceNode() const
39 {
40 	if ( this->kind != kCDataNode ) return false;
41 
42 	for ( size_t i = 0; i < this->value.size(); ++i ) {
43 		unsigned char ch = this->value[i];
44 		if ( IsWhitespaceChar ( ch ) ) continue;
45 		// *** Add checks for other whitespace characters.
46 		return false;	// All the checks failed, this isn't whitespace.
47 	}
48 
49 	return true;
50 
51 }	// XML_Node::IsWhitespaceNode
52 
53 // =================================================================================================
54 // XML_Node::IsLeafContentNode
55 //============================
56 
IsLeafContentNode() const57 bool XML_Node::IsLeafContentNode() const
58 {
59 	if ( this->kind != kElemNode ) return false;
60 	if ( this->content.size() == 0 ) return true;
61 	if ( this->content.size() > 1 ) return false;
62 	if ( this->content[0]->kind != kCDataNode ) return false;
63 
64 	return true;
65 
66 }	// XML_Node::IsLeafContentNode
67 
68 // =================================================================================================
69 // XML_Node::IsEmptyLeafNode
70 //==========================
71 
IsEmptyLeafNode() const72 bool XML_Node::IsEmptyLeafNode() const
73 {
74 
75 	if ( (this->kind != kElemNode) || (this->content.size() != 0) ) return false;
76 	return true;
77 
78 }	// XML_Node::IsEmptyLeafNode
79 
80 // =================================================================================================
81 // XML_Node::GetAttrValue
82 //=======================
83 
GetAttrValue(XMP_StringPtr attrName) const84 XMP_StringPtr XML_Node::GetAttrValue ( XMP_StringPtr attrName ) const
85 {
86 
87 	for ( size_t i = 0, aLim = this->attrs.size(); i < aLim; ++i ) {
88 		XML_Node * attrPtr = this->attrs[i];
89 		if ( ! attrPtr->ns.empty() ) continue;	// This form of GetAttrValue is for attrs in no namespace.
90 		if ( attrPtr->name == attrName ) return attrPtr->value.c_str();
91 	}
92 
93 	return 0;	// Not found.
94 
95 }	// XML_Node::GetAttrValue
96 
97 // =================================================================================================
98 // XML_Node::SetAttrValue
99 //=======================
100 
SetAttrValue(XMP_StringPtr attrName,XMP_StringPtr attrValue)101 void XML_Node::SetAttrValue ( XMP_StringPtr attrName, XMP_StringPtr attrValue )
102 {
103 
104 	for ( size_t i = 0, aLim = this->attrs.size(); i < aLim; ++i ) {
105 		XML_Node * attrPtr = this->attrs[i];
106 		if ( ! attrPtr->ns.empty() ) continue;	// This form of SetAttrValue is for attrs in no namespace.
107 		if ( attrPtr->name == attrName ) {
108 			attrPtr->value = attrValue;
109 			return;
110 		}
111 	}
112 
113 }	// XML_Node::SetAttrValue
114 
115 // =================================================================================================
116 // XML_Node::GetLeafContentValue
117 //==============================
118 
GetLeafContentValue() const119 XMP_StringPtr XML_Node::GetLeafContentValue() const
120 {
121 	if ( (! this->IsLeafContentNode()) || this->content.empty() ) return "";
122 
123 	return this->content[0]->value.c_str();
124 
125 }	// XML_Node::GetLeafContentValue
126 
127 // =================================================================================================
128 // XML_Node::SetLeafContentValue
129 //==============================
130 
SetLeafContentValue(XMP_StringPtr newValue)131 void XML_Node::SetLeafContentValue ( XMP_StringPtr newValue )
132 {
133 	XML_Node * valueNode;
134 
135 	if ( ! this->content.empty() ) {
136 		valueNode = this->content[0];
137 	} else {
138 		valueNode = new XML_Node ( this, "", kCDataNode );
139 		this->content.push_back ( valueNode );
140 	}
141 
142 	valueNode->value = newValue;
143 
144 }	// XML_Node::SetLeafContentValue
145 
146 // =================================================================================================
147 // XML_Node::CountNamedElements
148 //=============================
149 
CountNamedElements(XMP_StringPtr nsURI,XMP_StringPtr localName) const150 size_t XML_Node::CountNamedElements ( XMP_StringPtr nsURI, XMP_StringPtr localName ) const
151 {
152 	size_t count = 0;
153 
154 	for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) {
155 		const XML_Node & child = *this->content[i];
156 		if ( child.ns != nsURI ) continue;
157 		if ( strcmp ( localName, child.name.c_str()+child.nsPrefixLen ) != 0 ) continue;
158 		++count;
159 	}
160 
161 	return count;
162 
163 }	// XML_Node::CountNamedElements
164 
165 // =================================================================================================
166 // XML_Node::GetNamedElement
167 //==========================
168 
GetNamedElement(XMP_StringPtr nsURI,XMP_StringPtr localName,size_t which)169 XML_NodePtr XML_Node::GetNamedElement ( XMP_StringPtr nsURI, XMP_StringPtr localName, size_t which /* = 0 */ )
170 {
171 
172 	for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) {
173 		XML_Node * childPtr = this->content[i];
174 		if ( childPtr->ns != nsURI ) continue;
175 		if ( strcmp ( localName, childPtr->name.c_str()+childPtr->nsPrefixLen ) != 0 ) continue;
176 		if ( which == 0 ) return childPtr;
177 		--which;
178 	}
179 
180 	return 0;	/// Not found.
181 
182 }	// XML_Node::GetNamedElement
183 
184 // =================================================================================================
185 // DumpNodeList
186 // ============
187 
188 static const char * kNodeKinds[] = { "root", "elem", "attr", "cdata", "pi" };
189 
DumpNodeList(std::string * buffer,const XML_NodeVector & list,int indent)190 static void DumpNodeList ( std::string * buffer, const XML_NodeVector & list, int indent )
191 {
192 
193 	for ( size_t i = 0, limit = list.size(); i < limit; ++i ) {
194 
195 		const XML_Node * node = list[i];
196 
197 		for ( int t = indent; t > 0; --t ) *buffer += "  ";
198 		if ( node->IsWhitespaceNode() ) {
199 			*buffer += "-- whitespace --\n";
200 			continue;
201 		}
202 
203 		*buffer += node->name;
204 		*buffer += " - ";
205 		*buffer += kNodeKinds[node->kind];
206 		if ( ! node->value.empty() ) {
207 			*buffer += ", value=\"";
208 			*buffer += node->value;
209 			*buffer += "\"";
210 		}
211 		if ( ! node->ns.empty() ) {
212 			*buffer += ", ns=\"";
213 			*buffer += node->ns;
214 			*buffer += "\"";
215 		}
216 		if ( node->nsPrefixLen != 0 ) {
217 			*buffer += ", prefixLen=";
218 			char numBuf [20];
219 			snprintf ( numBuf, sizeof(numBuf), "%lu", (unsigned long)node->nsPrefixLen );
220 			*buffer += numBuf;
221 		}
222 		*buffer += "\n";
223 
224 		if ( ! node->attrs.empty() ) {
225 			for ( int t = indent+1; t > 0; --t ) *buffer += "  ";
226 			*buffer += "attrs:\n";
227 			DumpNodeList ( buffer, node->attrs, indent+2 );
228 		}
229 
230 		if ( ! node->content.empty() ) {
231 			DumpNodeList ( buffer, node->content, indent+1 );
232 		}
233 
234 	}
235 
236 }	// DumpNodeList
237 
238 // =================================================================================================
239 // XML_Node::Dump
240 //===============
241 
Dump(std::string * buffer)242 void XML_Node::Dump ( std::string * buffer )
243 {
244 
245 	*buffer = "Dump of XML_Node tree\n";
246 
247 	*buffer += "Root info: name=\"";
248 	*buffer += this->name;
249 	*buffer += "\", value=\"";
250 	*buffer += this->value;
251 	*buffer += "\", ns=\"";
252 	*buffer += this->ns;
253 	*buffer += "\", kind=";
254 	*buffer += kNodeKinds[this->kind];
255 	*buffer += "\n";
256 
257 	if ( ! this->attrs.empty() ) {
258 		*buffer += "  attrs:\n";
259 		DumpNodeList ( buffer, this->attrs, 2 );
260 	}
261 	*buffer += "\n";
262 
263 	DumpNodeList ( buffer, this->content, 0 );
264 
265 }	// XML_Node::Dump
266 
267 // =================================================================================================
268 // SerializeOneNode
269 // ================
270 
SerializeOneNode(std::string * buffer,const XML_Node & node)271 static void SerializeOneNode ( std::string * buffer, const XML_Node & node )
272 {
273 	size_t i, limit;
274 	XMP_StringPtr namePtr = node.name.c_str();
275 	if ( XMP_LitNMatch ( namePtr, "_dflt_:", 7 ) ) namePtr += 7;	// Hack for default namespaces.
276 
277 	switch ( node.kind ) {
278 
279 		case kElemNode:
280 			*buffer += '<';
281 			*buffer += namePtr;
282 			for ( i = 0, limit = node.attrs.size(); i < limit; ++i ) {
283 				SerializeOneNode ( buffer, *node.attrs[i] );
284 			}
285 			if ( node.content.empty() ) {
286 				*buffer += "/>";
287 			} else {
288 				*buffer += '>';
289 				for ( i = 0, limit = node.content.size(); i < limit; ++i ) {
290 					SerializeOneNode ( buffer, *node.content[i] );
291 				}
292 				*buffer += "</";
293 				*buffer += namePtr;
294 				*buffer += '>';
295 			}
296 			break;
297 
298 		case kAttrNode:
299 			*buffer += ' ';
300 			*buffer += namePtr;
301 			*buffer += "=\"";
302 			*buffer += node.value;
303 			*buffer += '"';
304 			break;
305 
306 		case kCDataNode:
307 			*buffer += node.value;
308 			break;
309 
310 		case kPINode:
311 			*buffer += node.value;	// *** Note that we're dropping PIs during the Expat parse.
312 			break;
313 
314 	}
315 
316 }	// SerializeOneNode
317 
318 // =================================================================================================
319 // CollectNamespaceDecls
320 // =====================
321 
322 typedef std::map < std::string, std::string > NamespaceMap;
323 
CollectNamespaceDecls(NamespaceMap * nsMap,const XML_Node & node)324 static void CollectNamespaceDecls ( NamespaceMap * nsMap, const XML_Node & node )
325 {
326 	size_t i, limit;
327 
328 	if ( ! node.ns.empty() ) {
329 		size_t nameMid = 0;
330 		while ( node.name[nameMid] != ':' ) ++nameMid;
331 		std::string prefix = node.name.substr ( 0, nameMid );
332 		(*nsMap)[prefix] = node.ns;
333 	}
334 
335 	if ( node.kind == kElemNode ) {
336 
337 		for ( i = 0, limit = node.attrs.size(); i < limit; ++i ) {
338 			CollectNamespaceDecls ( nsMap, *node.attrs[i] );
339 		}
340 
341 		for ( i = 0, limit = node.content.size(); i < limit; ++i ) {
342 			const XML_Node & content = *node.content[i];
343 			if ( content.kind == kElemNode ) CollectNamespaceDecls ( nsMap, content );
344 		}
345 
346 	}
347 
348 }	// CollectNamespaceDecls
349 
350 // =================================================================================================
351 // XML_Node::Serialize
352 //====================
353 
Serialize(std::string * buffer)354 void XML_Node::Serialize ( std::string * buffer )
355 {
356 	buffer->erase();
357 
358 	if ( this->kind != kRootNode ) {
359 
360 		SerializeOneNode ( buffer, *this );
361 
362 	} else {
363 
364 		// Do the outermost level here, in order to add the XML version and namespace declarations.
365 
366 		*buffer += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
367 
368 		for ( size_t outer = 0, oLimit = this->content.size(); outer < oLimit; ++outer ) {
369 
370 			const XML_Node & node = *this->content[outer];
371 
372 			if ( node.kind != kElemNode ) {
373 
374 				SerializeOneNode ( buffer, node );
375 
376 			} else {
377 
378 				XMP_StringPtr namePtr = node.name.c_str();
379 				if ( XMP_LitNMatch ( namePtr, "_dflt_:", 7 ) ) namePtr += 7;	// Hack for default namespaces.
380 
381 				*buffer += '<';
382 				*buffer += namePtr;
383 
384 				NamespaceMap nsMap;
385 				CollectNamespaceDecls ( &nsMap, node );
386 				NamespaceMap::iterator nsDecl = nsMap.begin();
387 				NamespaceMap::iterator nsEnd  = nsMap.end();
388 				for ( ; nsDecl != nsEnd; ++nsDecl ) {
389 					const std::string & prefix = nsDecl->first;
390 					*buffer += " xmlns";
391 					if ( prefix != "_dflt_" ) { *buffer += ':'; *buffer += prefix; }
392 					*buffer += "=\"";
393 					*buffer += nsDecl->second;
394 					*buffer += '"';
395 				}
396 
397 				for ( size_t attr = 0, aLimit = node.attrs.size(); attr < aLimit; ++attr ) {
398 					SerializeOneNode ( buffer, *node.attrs[attr] );
399 				}
400 
401 				if ( node.content.empty() ) {
402 					*buffer += "/>";
403 				} else {
404 					*buffer += '>';
405 					for ( size_t child = 0, cLimit = node.content.size(); child < cLimit; ++child ) {
406 						SerializeOneNode ( buffer, *node.content[child] );
407 					}
408 					*buffer += "</";
409 					*buffer += namePtr;
410 					*buffer += '>';
411 				}
412 
413 			}
414 
415 		}
416 
417 	}
418 
419 
420 }	// XML_Node::Serialize
421 
422 // =================================================================================================
423 // XML_Node::RemoveAttrs
424 //======================
425 
RemoveAttrs()426 void XML_Node::RemoveAttrs()
427 {
428 
429 	for ( size_t i = 0, vLim = this->attrs.size(); i < vLim; ++i ) delete this->attrs[i];
430 	this->attrs.clear();
431 
432 }	// XML_Node::RemoveAttrs
433 
434 // =================================================================================================
435 // XML_Node::RemoveContent
436 //========================
437 
RemoveContent()438 void XML_Node::RemoveContent()
439 {
440 
441 	for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) delete this->content[i];
442 	this->content.clear();
443 
444 }	// XML_Node::RemoveContent
445 
446 // =================================================================================================
447 // XML_Node::ClearNode
448 //====================
449 
ClearNode()450 void XML_Node::ClearNode()
451 {
452 
453 	this->kind = 0;
454 	this->ns.erase();
455 	this->name.erase();
456 	this->value.erase();
457 
458 	this->RemoveAttrs();
459 	this->RemoveContent();
460 
461 }	// XML_Node::ClearNode
462 
463 // =================================================================================================
464