Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 : #include "sal/config.h"
20 :
21 : #include <iterator> /* std::iterator*/
22 :
23 : #include <cassert>
24 : #include <stdio.h>
25 : #include <sal/alloca.h>
26 :
27 : #include "helper.hxx"
28 : #include "common.hxx"
29 : #include "xmlparse.hxx"
30 : #include <fstream>
31 : #include <iostream>
32 : #include <osl/mutex.hxx>
33 : #include <osl/thread.hxx>
34 : #include <osl/process.h>
35 : #include <rtl/strbuf.hxx>
36 : #include <unicode/regex.h>
37 :
38 : using namespace U_ICU_NAMESPACE;
39 : using namespace std;
40 : using namespace osl;
41 :
42 : #define XML_LANG "xml-lang"
43 : #define ID "id"
44 : #define OLDREF "oldref"
45 :
46 :
47 : // class XMLChildNode
48 :
49 :
50 0 : XMLChildNode::XMLChildNode( XMLParentNode *pPar )
51 0 : : m_pParent( pPar )
52 : {
53 0 : if ( m_pParent )
54 0 : m_pParent->AddChild( this );
55 0 : }
56 :
57 :
58 0 : XMLChildNode::XMLChildNode( const XMLChildNode& rObj)
59 : : XMLNode(rObj),
60 0 : m_pParent(rObj.m_pParent)
61 : {
62 0 : }
63 :
64 0 : XMLChildNode& XMLChildNode::operator=(const XMLChildNode& rObj)
65 : {
66 0 : if(this != &rObj)
67 : {
68 0 : m_pParent=rObj.m_pParent;
69 : }
70 0 : return *this;
71 : }
72 :
73 :
74 : // class XMLParentNode
75 :
76 :
77 0 : XMLParentNode::~XMLParentNode()
78 : {
79 0 : if( m_pChildList )
80 : {
81 0 : RemoveAndDeleteAllChildren();
82 0 : delete m_pChildList;
83 : }
84 0 : m_pChildList = NULL;
85 0 : }
86 0 : XMLParentNode::XMLParentNode( const XMLParentNode& rObj)
87 0 : : XMLChildNode( rObj )
88 : {
89 0 : if( rObj.m_pChildList )
90 : {
91 0 : m_pChildList=new XMLChildNodeList();
92 0 : for ( size_t i = 0; i < rObj.m_pChildList->size(); i++ )
93 : {
94 0 : XMLChildNode* pNode = (*rObj.m_pChildList)[ i ];
95 0 : if( pNode != NULL)
96 : {
97 0 : switch(pNode->GetNodeType())
98 : {
99 : case XML_NODE_TYPE_ELEMENT:
100 0 : AddChild( new XMLElement( *static_cast<XMLElement* >(pNode) ) ); break;
101 : case XML_NODE_TYPE_DATA:
102 0 : AddChild( new XMLData ( *static_cast<XMLData* > (pNode) ) ); break;
103 : case XML_NODE_TYPE_COMMENT:
104 0 : AddChild( new XMLComment( *static_cast<XMLComment* >(pNode) ) ); break;
105 : case XML_NODE_TYPE_DEFAULT:
106 0 : AddChild( new XMLDefault( *static_cast<XMLDefault* >(pNode) ) ); break;
107 0 : default: fprintf(stdout,"XMLParentNode::XMLParentNode( const XMLParentNode& rObj) strange obj");
108 : }
109 : }
110 : }
111 : }
112 : else
113 0 : m_pChildList = NULL;
114 0 : }
115 0 : XMLParentNode& XMLParentNode::operator=(const XMLParentNode& rObj)
116 : {
117 0 : if(this!=&rObj)
118 : {
119 0 : XMLChildNode::operator=(rObj);
120 0 : if( m_pChildList )
121 : {
122 0 : RemoveAndDeleteAllChildren();
123 0 : delete m_pChildList;
124 0 : m_pChildList = NULL;
125 : }
126 0 : if( rObj.m_pChildList )
127 : {
128 0 : m_pChildList=new XMLChildNodeList();
129 0 : for ( size_t i = 0; i < rObj.m_pChildList->size(); i++ )
130 0 : AddChild( (*rObj.m_pChildList)[ i ] );
131 : }
132 : else
133 0 : m_pChildList = NULL;
134 :
135 : }
136 0 : return *this;
137 : }
138 0 : void XMLParentNode::AddChild( XMLChildNode *pChild )
139 : {
140 0 : if ( !m_pChildList )
141 0 : m_pChildList = new XMLChildNodeList();
142 0 : m_pChildList->push_back( pChild );
143 0 : }
144 :
145 0 : void XMLParentNode::RemoveAndDeleteAllChildren()
146 : {
147 0 : if ( m_pChildList )
148 : {
149 0 : for ( size_t i = 0; i < m_pChildList->size(); i++ )
150 0 : delete (*m_pChildList)[ i ];
151 0 : m_pChildList->clear();
152 : }
153 0 : }
154 :
155 :
156 : // class XMLFile
157 :
158 :
159 0 : void XMLFile::Write( OString const &aFilename )
160 : {
161 : std::ofstream s(
162 0 : aFilename.getStr(), std::ios_base::out | std::ios_base::trunc);
163 0 : if (!s.is_open())
164 : {
165 : std::cerr
166 0 : << "Error: helpex cannot create file " << aFilename.getStr()
167 0 : << '\n';
168 0 : std::exit(EXIT_FAILURE);
169 : }
170 0 : Write(s);
171 0 : s.close();
172 0 : }
173 :
174 0 : bool XMLFile::Write( ofstream &rStream , XMLNode *pCur )
175 : {
176 0 : if ( !pCur )
177 0 : Write( rStream, this );
178 : else {
179 0 : switch( pCur->GetNodeType())
180 : {
181 : case XML_NODE_TYPE_FILE:
182 : {
183 0 : if( GetChildList())
184 0 : for ( size_t i = 0; i < GetChildList()->size(); i++ )
185 0 : Write( rStream, (*GetChildList())[ i ] );
186 : }
187 0 : break;
188 : case XML_NODE_TYPE_ELEMENT:
189 : {
190 0 : XMLElement *pElement = static_cast<XMLElement*>(pCur);
191 0 : rStream << "<";
192 0 : rStream << pElement->GetName().getStr();
193 0 : if ( pElement->GetAttributeList())
194 0 : for ( size_t j = 0; j < pElement->GetAttributeList()->size(); j++ )
195 : {
196 0 : rStream << " ";
197 0 : OString sData( (*pElement->GetAttributeList())[ j ]->GetName() );
198 0 : rStream << XMLUtil::QuotHTML( sData ).getStr();
199 0 : rStream << "=\"";
200 0 : sData = (*pElement->GetAttributeList())[ j ]->GetValue();
201 0 : rStream << XMLUtil::QuotHTML( sData ).getStr();
202 0 : rStream << "\"";
203 0 : }
204 0 : if ( !pElement->GetChildList())
205 0 : rStream << "/>";
206 : else
207 : {
208 0 : rStream << ">";
209 0 : for ( size_t k = 0; k < pElement->GetChildList()->size(); k++ )
210 0 : Write( rStream, (*pElement->GetChildList())[ k ] );
211 0 : rStream << "</";
212 0 : rStream << pElement->GetName().getStr();
213 0 : rStream << ">";
214 : }
215 : }
216 0 : break;
217 : case XML_NODE_TYPE_DATA:
218 : {
219 0 : OString sData( static_cast<const XMLData*>(pCur)->GetData());
220 0 : rStream << XMLUtil::QuotHTML( sData ).getStr();
221 : }
222 0 : break;
223 : case XML_NODE_TYPE_COMMENT:
224 : {
225 0 : const XMLComment *pComment = static_cast<const XMLComment*>(pCur);
226 0 : rStream << "<!--";
227 0 : rStream << pComment->GetComment().getStr();
228 0 : rStream << "-->";
229 : }
230 0 : break;
231 : case XML_NODE_TYPE_DEFAULT:
232 : {
233 0 : const XMLDefault *pDefault = static_cast<const XMLDefault*>(pCur);
234 0 : rStream << pDefault->GetDefault().getStr();
235 : }
236 0 : break;
237 : }
238 : }
239 0 : return true;
240 : }
241 :
242 0 : void XMLFile::Print( XMLNode *pCur, sal_uInt16 nLevel )
243 : {
244 0 : if ( !pCur )
245 0 : Print( this );
246 : else
247 : {
248 0 : switch( pCur->GetNodeType())
249 : {
250 : case XML_NODE_TYPE_FILE:
251 : {
252 0 : if( GetChildList())
253 0 : for ( size_t i = 0; i < GetChildList()->size(); i++ )
254 0 : Print( (*GetChildList())[ i ] );
255 : }
256 0 : break;
257 : case XML_NODE_TYPE_ELEMENT:
258 : {
259 0 : XMLElement *pElement = static_cast<XMLElement*>(pCur);
260 :
261 0 : fprintf( stdout, "<%s", pElement->GetName().getStr());
262 0 : if ( pElement->GetAttributeList())
263 : {
264 0 : for (size_t j = 0; j < pElement->GetAttributeList()->size(); ++j)
265 : {
266 0 : const OString aAttrName((*pElement->GetAttributeList())[j]->GetName());
267 0 : if (!aAttrName.equalsIgnoreAsciiCase(XML_LANG))
268 : {
269 : fprintf( stdout, " %s=\"%s\"",
270 : aAttrName.getStr(),
271 0 : (*pElement->GetAttributeList())[ j ]->GetValue().getStr());
272 : }
273 0 : }
274 : }
275 0 : if ( !pElement->GetChildList())
276 0 : fprintf( stdout, "/>" );
277 : else
278 : {
279 0 : fprintf( stdout, ">" );
280 0 : for ( size_t k = 0; k < pElement->GetChildList()->size(); k++ )
281 0 : Print( (*pElement->GetChildList())[ k ], nLevel + 1 );
282 0 : fprintf( stdout, "</%s>", pElement->GetName().getStr());
283 : }
284 : }
285 0 : break;
286 : case XML_NODE_TYPE_DATA:
287 : {
288 0 : const XMLData *pData = static_cast<const XMLData*>(pCur);
289 0 : fprintf( stdout, "%s", pData->GetData().getStr());
290 : }
291 0 : break;
292 : case XML_NODE_TYPE_COMMENT:
293 : {
294 0 : const XMLComment *pComment = static_cast<const XMLComment*>(pCur);
295 0 : fprintf( stdout, "<!--%s-->", pComment->GetComment().getStr());
296 : }
297 0 : break;
298 : case XML_NODE_TYPE_DEFAULT:
299 : {
300 0 : const XMLDefault *pDefault = static_cast<const XMLDefault*>(pCur);
301 0 : fprintf( stdout, "%s", pDefault->GetDefault().getStr());
302 : }
303 0 : break;
304 : }
305 : }
306 0 : }
307 0 : XMLFile::~XMLFile()
308 : {
309 0 : if( m_pXMLStrings != NULL )
310 : {
311 0 : XMLHashMap::iterator pos = m_pXMLStrings->begin();
312 0 : for( ; pos != m_pXMLStrings->end() ; ++pos )
313 : {
314 0 : delete pos->second; // Check and delete content also ?
315 : }
316 0 : delete m_pXMLStrings;
317 0 : m_pXMLStrings = NULL;
318 : }
319 0 : }
320 0 : XMLFile::XMLFile( const OString &rFileName ) // the file name, empty if created from memory stream
321 : : XMLParentNode( NULL )
322 : , m_sFileName( rFileName )
323 0 : , m_pXMLStrings( NULL )
324 : {
325 0 : m_aNodes_localize.insert( TagMap::value_type(OString("bookmark") , sal_True) );
326 0 : m_aNodes_localize.insert( TagMap::value_type(OString("variable") , sal_True) );
327 0 : m_aNodes_localize.insert( TagMap::value_type(OString("paragraph") , sal_True) );
328 0 : m_aNodes_localize.insert( TagMap::value_type(OString("alt") , sal_True) );
329 0 : m_aNodes_localize.insert( TagMap::value_type(OString("caption") , sal_True) );
330 0 : m_aNodes_localize.insert( TagMap::value_type(OString("title") , sal_True) );
331 0 : m_aNodes_localize.insert( TagMap::value_type(OString("link") , sal_True) );
332 0 : }
333 :
334 0 : void XMLFile::Extract( XMLFile *pCur )
335 : {
336 0 : if( m_pXMLStrings )
337 0 : delete m_pXMLStrings; // Elements ?
338 :
339 0 : m_pXMLStrings = new XMLHashMap();
340 0 : if ( !pCur )
341 0 : SearchL10NElements( this );
342 : else
343 : {
344 0 : if( pCur->GetNodeType() == XML_NODE_TYPE_FILE )
345 : {
346 0 : SearchL10NElements(pCur);
347 : }
348 : }
349 0 : }
350 :
351 0 : void XMLFile::InsertL10NElement( XMLElement* pElement )
352 : {
353 0 : OString sId, sLanguage("");
354 : LangHashMap* pElem;
355 :
356 0 : if( pElement->GetAttributeList() != NULL )
357 : {
358 0 : for ( size_t j = 0; j < pElement->GetAttributeList()->size(); j++ )
359 : {
360 0 : const OString sTempStr((*pElement->GetAttributeList())[ j ]->GetName());
361 : // Get the "id" Attribute
362 0 : if (sTempStr == ID)
363 : {
364 0 : sId = (*pElement->GetAttributeList())[ j ]->GetValue();
365 : }
366 : // Get the "xml-lang" Attribute
367 0 : if (sTempStr == XML_LANG)
368 : {
369 0 : sLanguage = (*pElement->GetAttributeList())[j]->GetValue();
370 : }
371 :
372 0 : }
373 : }
374 : else
375 : {
376 0 : fprintf(stdout,"XMLFile::InsertL10NElement: No AttributeList found");
377 0 : fprintf(stdout,"++++++++++++++++++++++++++++++++++++++++++++++++++");
378 0 : Print( pElement , 0 );
379 0 : fprintf(stdout,"++++++++++++++++++++++++++++++++++++++++++++++++++");
380 : }
381 :
382 0 : XMLHashMap::iterator pos = m_pXMLStrings->find( sId );
383 0 : if( pos == m_pXMLStrings->end() ) // No instanze , create new one
384 : {
385 0 : pElem = new LangHashMap();
386 0 : (*pElem)[ sLanguage ]=pElement;
387 0 : m_pXMLStrings->insert( XMLHashMap::value_type( sId , pElem ) );
388 0 : m_vOrder.push_back( sId );
389 : }
390 : else // Already there
391 : {
392 0 : pElem=pos->second;
393 0 : if ( (*pElem)[ sLanguage ] )
394 : {
395 0 : fprintf(stdout,"Error: Duplicated entry. ID = %s LANG = %s in File %s\n", sId.getStr(), sLanguage.getStr(), m_sFileName.getStr() );
396 0 : exit( -1 );
397 : }
398 0 : (*pElem)[ sLanguage ]=pElement;
399 0 : }
400 0 : }
401 :
402 0 : XMLFile::XMLFile( const XMLFile& rObj )
403 : : XMLParentNode( rObj )
404 : , m_sFileName( rObj.m_sFileName )
405 0 : , m_pXMLStrings( 0 )
406 : {
407 0 : if( this != &rObj )
408 : {
409 0 : m_aNodes_localize = rObj.m_aNodes_localize;
410 0 : m_vOrder = rObj.m_vOrder;
411 : }
412 0 : }
413 :
414 0 : XMLFile& XMLFile::operator=(const XMLFile& rObj)
415 : {
416 0 : if( this != &rObj )
417 : {
418 0 : XMLParentNode::operator=(rObj);
419 :
420 0 : m_aNodes_localize = rObj.m_aNodes_localize;
421 0 : m_vOrder = rObj.m_vOrder;
422 :
423 0 : if( m_pXMLStrings )
424 0 : delete m_pXMLStrings;
425 :
426 0 : if( rObj.m_pXMLStrings )
427 : {
428 0 : m_pXMLStrings = new XMLHashMap();
429 0 : for( XMLHashMap::iterator pos = rObj.m_pXMLStrings->begin() ; pos != rObj.m_pXMLStrings->end() ; ++pos )
430 : {
431 0 : LangHashMap* pElem=pos->second;
432 0 : LangHashMap* pNewelem = new LangHashMap();
433 0 : for(LangHashMap::iterator pos2=pElem->begin(); pos2!=pElem->end();++pos2)
434 : {
435 0 : (*pNewelem)[ pos2->first ] = new XMLElement( *pos2->second );
436 : }
437 0 : (*m_pXMLStrings)[ pos->first ] = pNewelem;
438 : }
439 : }
440 : }
441 0 : return *this;
442 : }
443 :
444 0 : void XMLFile::SearchL10NElements( XMLChildNode *pCur, int nPos )
445 : {
446 0 : bool bInsert = true;
447 0 : if ( !pCur )
448 0 : SearchL10NElements( this );
449 : else
450 : {
451 0 : switch( pCur->GetNodeType())
452 : {
453 : case XML_NODE_TYPE_FILE:
454 : {
455 : XMLChildNode* pElement;
456 0 : if( GetChildList())
457 : {
458 0 : for ( size_t i = 0; i < GetChildList()->size(); i++ )
459 : {
460 0 : pElement = (*GetChildList())[ i ];
461 0 : if( pElement->GetNodeType() == XML_NODE_TYPE_ELEMENT )
462 0 : SearchL10NElements( pElement , i);
463 : }
464 : }
465 : }
466 0 : break;
467 : case XML_NODE_TYPE_ELEMENT:
468 : {
469 0 : XMLElement *pElement = static_cast<XMLElement*>(pCur);
470 0 : const OString sName(pElement->GetName().toAsciiLowerCase());
471 0 : OString sLanguage, sTmpStrVal, sOldref;
472 0 : if ( pElement->GetAttributeList())
473 : {
474 0 : for ( size_t j = 0 , cnt = pElement->GetAttributeList()->size(); j < cnt && bInsert; ++j )
475 : {
476 0 : const OString sTmpStr = (*pElement->GetAttributeList())[j]->GetName();
477 0 : if (sTmpStr == ID)
478 : {
479 0 : sTmpStrVal=(*pElement->GetAttributeList())[ j ]->GetValue();
480 : }
481 0 : if (sTmpStr == "localize")
482 : {
483 0 : bInsert=false;
484 : }
485 0 : if (sTmpStr == XML_LANG) // Get the "xml-lang" Attribute
486 : {
487 0 : sLanguage=(*pElement->GetAttributeList())[ j ]->GetValue();
488 : }
489 0 : if (sTmpStr == OLDREF) // Get the "oldref" Attribute
490 : {
491 0 : sOldref=(*pElement->GetAttributeList())[ j ]->GetValue();
492 : }
493 0 : }
494 0 : pElement->SetLanguageId( sLanguage );
495 0 : pElement->SetId( sTmpStrVal );
496 0 : pElement->SetOldRef( sOldref );
497 0 : pElement->SetPos( nPos );
498 : }
499 :
500 0 : if ( bInsert && ( m_aNodes_localize.find( sName ) != m_aNodes_localize.end() ) )
501 0 : InsertL10NElement(pElement);
502 0 : else if ( bInsert && pElement->GetChildList() )
503 : {
504 0 : for ( size_t k = 0; k < pElement->GetChildList()->size(); k++ )
505 0 : SearchL10NElements( (*pElement->GetChildList())[ k ], k);
506 0 : }
507 : }
508 0 : break;
509 : case XML_NODE_TYPE_DATA:
510 0 : break;
511 : case XML_NODE_TYPE_COMMENT:
512 0 : break;
513 : case XML_NODE_TYPE_DEFAULT:
514 0 : break;
515 : }
516 : }
517 0 : }
518 :
519 0 : bool XMLFile::CheckExportStatus( XMLParentNode *pCur )
520 : {
521 : static bool bStatusExport = true;
522 :
523 0 : bool bInsert = true;
524 0 : if ( !pCur )
525 0 : CheckExportStatus( this );
526 : else {
527 0 : switch( pCur->GetNodeType())
528 : {
529 : case XML_NODE_TYPE_FILE:
530 : {
531 0 : if( GetChildList())
532 : {
533 0 : for ( size_t i = 0; i < GetChildList()->size(); i++ )
534 : {
535 0 : XMLParentNode* pElement = static_cast<XMLParentNode*>((*GetChildList())[ i ]);
536 0 : if( pElement->GetNodeType() == XML_NODE_TYPE_ELEMENT ) CheckExportStatus( pElement );//, i);
537 : }
538 : }
539 : }
540 0 : break;
541 : case XML_NODE_TYPE_ELEMENT:
542 : {
543 0 : XMLElement *pElement = static_cast<XMLElement*>(pCur);
544 0 : if (pElement->GetName().equalsIgnoreAsciiCase("TOPIC"))
545 : {
546 0 : if ( pElement->GetAttributeList())
547 : {
548 0 : for (size_t j = 0 , cnt = pElement->GetAttributeList()->size(); j < cnt && bInsert; ++j)
549 : {
550 0 : const OString tmpStr((*pElement->GetAttributeList())[j]->GetName());
551 0 : if (tmpStr.equalsIgnoreAsciiCase("STATUS"))
552 : {
553 0 : const OString tmpStrVal((*pElement->GetAttributeList())[j]->GetValue());
554 0 : if (!tmpStrVal.equalsIgnoreAsciiCase("PUBLISH") &&
555 0 : !tmpStrVal.equalsIgnoreAsciiCase("DEPRECATED"))
556 : {
557 0 : bStatusExport = false;
558 0 : }
559 : }
560 :
561 0 : }
562 : }
563 : }
564 0 : else if ( pElement->GetChildList() )
565 : {
566 0 : for (size_t k = 0; k < pElement->GetChildList()->size(); ++k)
567 0 : CheckExportStatus( static_cast<XMLParentNode*>((*pElement->GetChildList())[k]) );
568 : }
569 : }
570 0 : break;
571 : }
572 : }
573 0 : return bStatusExport;
574 : }
575 :
576 0 : XMLElement::XMLElement(
577 : const OString &rName, // the element name
578 : XMLParentNode *pParent // parent node of this element
579 : )
580 : : XMLParentNode( pParent )
581 : , m_sElementName( rName )
582 : , m_pAttributes( NULL )
583 : , m_sProject(OString())
584 : , m_sFilename(OString())
585 : , m_sId(OString())
586 : , m_sOldRef(OString())
587 : , m_sResourceType(OString())
588 : , m_sLanguageId(OString())
589 0 : , m_nPos(0)
590 : {
591 0 : }
592 :
593 0 : XMLElement::XMLElement(const XMLElement& rObj)
594 : : XMLParentNode( rObj )
595 : , m_sElementName( rObj.m_sElementName )
596 : , m_pAttributes( 0 )
597 : , m_sProject( rObj.m_sProject )
598 : , m_sFilename( rObj.m_sFilename )
599 : , m_sId( rObj.m_sId )
600 : , m_sOldRef( rObj.m_sOldRef )
601 : , m_sResourceType( rObj.m_sResourceType )
602 : , m_sLanguageId( rObj.m_sLanguageId )
603 0 : , m_nPos( rObj.m_nPos )
604 : {
605 0 : if ( rObj.m_pAttributes )
606 : {
607 0 : m_pAttributes = new XMLAttributeList();
608 0 : for ( size_t i = 0; i < rObj.m_pAttributes->size(); i++ )
609 0 : AddAttribute( (*rObj.m_pAttributes)[ i ]->GetName(), (*rObj.m_pAttributes)[ i ]->GetValue() );
610 : }
611 0 : }
612 :
613 0 : XMLElement& XMLElement::operator=(const XMLElement& rObj)
614 : {
615 0 : if( this !=& rObj )
616 : {
617 0 : XMLParentNode::operator=(rObj);
618 0 : m_sElementName = rObj.m_sElementName;
619 0 : m_sProject = rObj.m_sProject;
620 0 : m_sFilename = rObj.m_sFilename;
621 0 : m_sId = rObj.m_sId;
622 0 : m_sOldRef = rObj.m_sOldRef;
623 0 : m_sResourceType = rObj.m_sResourceType;
624 0 : m_sLanguageId = rObj.m_sLanguageId;
625 0 : m_nPos = rObj.m_nPos;
626 :
627 0 : if ( m_pAttributes )
628 : {
629 0 : for ( size_t i = 0; i < m_pAttributes->size(); i++ )
630 0 : delete (*m_pAttributes)[ i ];
631 0 : delete m_pAttributes;
632 : }
633 0 : if ( rObj.m_pAttributes )
634 : {
635 0 : m_pAttributes = new XMLAttributeList();
636 0 : for ( size_t i = 0; i < rObj.m_pAttributes->size(); i++ )
637 0 : AddAttribute( (*rObj.m_pAttributes)[ i ]->GetName(), (*rObj.m_pAttributes)[ i ]->GetValue() );
638 : }
639 : }
640 0 : return *this;
641 : }
642 :
643 0 : void XMLElement::AddAttribute( const OString &rAttribute, const OString &rValue )
644 : {
645 0 : if ( !m_pAttributes )
646 0 : m_pAttributes = new XMLAttributeList();
647 0 : m_pAttributes->push_back( new XMLAttribute( rAttribute, rValue ) );
648 0 : }
649 :
650 0 : void XMLElement::ChangeLanguageTag( const OString &rValue )
651 : {
652 0 : SetLanguageId(rValue);
653 0 : if ( m_pAttributes )
654 : {
655 0 : for (size_t i = 0; i < m_pAttributes->size(); ++i)
656 : {
657 0 : if ( (*m_pAttributes)[ i ]->GetName() == "xml-lang" )
658 0 : (*m_pAttributes)[ i ]->setValue(rValue);
659 : }
660 : }
661 0 : XMLChildNodeList* pCList = GetChildList();
662 :
663 0 : if( pCList )
664 : {
665 0 : for ( size_t i = 0; i < pCList->size(); i++ )
666 : {
667 0 : XMLChildNode* pNode = (*pCList)[ i ];
668 0 : if( pNode && pNode->GetNodeType() == XML_NODE_TYPE_ELEMENT )
669 : {
670 0 : XMLElement* pElem = static_cast< XMLElement* >(pNode);
671 0 : pElem->ChangeLanguageTag( rValue );
672 0 : pElem->SetLanguageId(rValue);
673 0 : pElem = NULL;
674 0 : pNode = NULL;
675 : }
676 : }
677 0 : pCList = NULL;
678 : }
679 0 : }
680 :
681 0 : XMLElement::~XMLElement()
682 : {
683 0 : if ( m_pAttributes )
684 : {
685 0 : for ( size_t i = 0; i < m_pAttributes->size(); i++ )
686 0 : delete (*m_pAttributes)[ i ];
687 :
688 0 : delete m_pAttributes;
689 0 : m_pAttributes = NULL;
690 : }
691 0 : }
692 :
693 0 : OString XMLElement::ToOString()
694 : {
695 0 : OStringBuffer sBuffer;
696 0 : Print(this,sBuffer,true);
697 0 : return sBuffer.makeStringAndClear();
698 : }
699 :
700 0 : void XMLElement::Print(XMLNode *pCur, OStringBuffer& rBuffer, bool bRootelement ) const
701 : {
702 0 : if( pCur )
703 : {
704 0 : if( bRootelement )
705 : {
706 0 : XMLElement *pElement = static_cast<XMLElement*>(pCur);
707 0 : if ( pElement->GetAttributeList())
708 : {
709 0 : if ( pElement->GetChildList())
710 : {
711 0 : for ( size_t k = 0; k < pElement->GetChildList()->size(); k++ )
712 : {
713 0 : XMLChildNode* pTmp = (*pElement->GetChildList())[ k ];
714 0 : Print( pTmp, rBuffer , false);
715 : }
716 : }
717 : }
718 : }
719 : else
720 : {
721 0 : switch( pCur->GetNodeType())
722 : {
723 : case XML_NODE_TYPE_ELEMENT:
724 : {
725 0 : XMLElement *pElement = static_cast<XMLElement*>(pCur);
726 :
727 0 : if( !pElement->GetName().equalsIgnoreAsciiCase("comment") )
728 : {
729 0 : rBuffer.append( "<" );
730 0 : rBuffer.append( pElement->GetName() );
731 0 : if ( pElement->GetAttributeList())
732 : {
733 0 : for ( size_t j = 0; j < pElement->GetAttributeList()->size(); j++ )
734 : {
735 0 : const OString aAttrName( (*pElement->GetAttributeList())[ j ]->GetName() );
736 0 : if( !aAttrName.equalsIgnoreAsciiCase( "xml-lang" ) )
737 : {
738 : rBuffer.append(
739 0 : " " + aAttrName + "=\"" +
740 0 : (*pElement->GetAttributeList())[ j ]->GetValue() + "\"" );
741 : }
742 0 : }
743 : }
744 0 : if ( !pElement->GetChildList())
745 0 : rBuffer.append( "/>" );
746 : else
747 : {
748 0 : rBuffer.append( ">" );
749 0 : for ( size_t k = 0; k < pElement->GetChildList()->size(); k++ )
750 : {
751 0 : XMLChildNode* pTmp = (*pElement->GetChildList())[ k ];
752 0 : Print( pTmp, rBuffer , false);
753 : }
754 0 : rBuffer.append( "</" + pElement->GetName() + ">" );
755 : }
756 : }
757 : }
758 0 : break;
759 : case XML_NODE_TYPE_DATA:
760 : {
761 0 : const XMLData *pData = static_cast<const XMLData*>(pCur);
762 0 : rBuffer.append( pData->GetData() );
763 : }
764 0 : break;
765 : case XML_NODE_TYPE_COMMENT:
766 : {
767 0 : const XMLComment *pComment = static_cast<const XMLComment*>(pCur);
768 0 : rBuffer.append( "<!--" + pComment->GetComment() + "-->" );
769 : }
770 0 : break;
771 : case XML_NODE_TYPE_DEFAULT:
772 : {
773 0 : const XMLDefault *pDefault = static_cast<const XMLDefault*>(pCur);
774 0 : rBuffer.append( pDefault->GetDefault() );
775 : }
776 0 : break;
777 : }
778 : }
779 : }
780 : else
781 : {
782 0 : fprintf(stdout,"\n#+------Error: NULL Pointer in XMLELement::Print------+#\n");
783 0 : return;
784 : }
785 : }
786 :
787 :
788 : // class SimpleXMLParser
789 :
790 :
791 : namespace
792 : {
793 :
794 0 : static OUString lcl_pathnameToAbsoluteUrl(const OString& rPathname)
795 : {
796 0 : OUString sPath = OStringToOUString(rPathname, RTL_TEXTENCODING_UTF8 );
797 0 : OUString sUrl;
798 0 : if (osl::FileBase::getFileURLFromSystemPath(sPath, sUrl)
799 : != osl::FileBase::E_None)
800 : {
801 0 : std::cerr << "Error: Cannot convert input pathname to URL\n";
802 0 : std::exit(EXIT_FAILURE);
803 : }
804 0 : OUString sCwd;
805 0 : if (osl_getProcessWorkingDir(&sCwd.pData) != osl_Process_E_None)
806 : {
807 0 : std::cerr << "Error: Cannot determine cwd\n";
808 0 : std::exit(EXIT_FAILURE);
809 : }
810 0 : if (osl::FileBase::getAbsoluteFileURL(sCwd, sUrl, sUrl)
811 : != osl::FileBase::E_None)
812 : {
813 0 : std::cerr << "Error: Cannot convert input URL to absolute URL\n";
814 0 : std::exit(EXIT_FAILURE);
815 : }
816 0 : return sUrl;
817 : }
818 : }
819 :
820 :
821 0 : SimpleXMLParser::SimpleXMLParser()
822 : : m_pXMLFile(NULL)
823 : , m_pCurNode(NULL)
824 0 : , m_pCurData(NULL)
825 : {
826 0 : m_aParser = XML_ParserCreate( NULL );
827 0 : XML_SetUserData( m_aParser, this );
828 0 : XML_SetElementHandler( m_aParser, reinterpret_cast<XML_StartElementHandler>(StartElementHandler), reinterpret_cast<XML_EndElementHandler>(EndElementHandler) );
829 0 : XML_SetCharacterDataHandler( m_aParser, reinterpret_cast<XML_CharacterDataHandler>(CharacterDataHandler) );
830 0 : XML_SetCommentHandler( m_aParser, reinterpret_cast<XML_CommentHandler>(CommentHandler) );
831 0 : XML_SetDefaultHandler( m_aParser, reinterpret_cast<XML_DefaultHandler>(DefaultHandler) );
832 0 : }
833 :
834 0 : SimpleXMLParser::~SimpleXMLParser()
835 : {
836 0 : XML_ParserFree( m_aParser );
837 0 : }
838 :
839 0 : void SimpleXMLParser::StartElementHandler(
840 : void *userData, const XML_Char *name, const XML_Char **atts )
841 : {
842 0 : static_cast<SimpleXMLParser *>(userData)->StartElement( name, atts );
843 0 : }
844 :
845 0 : void SimpleXMLParser::EndElementHandler(
846 : void *userData, const XML_Char *name )
847 : {
848 0 : static_cast<SimpleXMLParser *>(userData)->EndElement( name );
849 0 : }
850 :
851 0 : void SimpleXMLParser::CharacterDataHandler(
852 : void *userData, const XML_Char *s, int len )
853 : {
854 0 : static_cast<SimpleXMLParser *>(userData)->CharacterData( s, len );
855 0 : }
856 :
857 0 : void SimpleXMLParser::CommentHandler(
858 : void *userData, const XML_Char *data )
859 : {
860 0 : static_cast<SimpleXMLParser *>(userData)->Comment( data );
861 0 : }
862 :
863 0 : void SimpleXMLParser::DefaultHandler(
864 : void *userData, const XML_Char *s, int len )
865 : {
866 0 : static_cast<SimpleXMLParser *>(userData)->Default( s, len );
867 0 : }
868 :
869 0 : void SimpleXMLParser::StartElement(
870 : const XML_Char *name, const XML_Char **atts )
871 : {
872 0 : XMLElement *pElement = new XMLElement( OString(name), m_pCurNode );
873 0 : m_pCurNode = pElement;
874 0 : m_pCurData = NULL;
875 :
876 0 : int i = 0;
877 0 : while( atts[i] )
878 : {
879 0 : pElement->AddAttribute( atts[ i ], atts[ i + 1 ] );
880 0 : i += 2;
881 : }
882 0 : }
883 :
884 0 : void SimpleXMLParser::EndElement( const XML_Char * /*name*/ )
885 : {
886 0 : m_pCurNode = m_pCurNode->GetParent();
887 0 : m_pCurData = NULL;
888 0 : }
889 :
890 0 : void SimpleXMLParser::CharacterData( const XML_Char *s, int len )
891 : {
892 0 : if ( !m_pCurData )
893 : {
894 0 : OString x( s, len );
895 0 : m_pCurData = new XMLData( helper::UnQuotHTML(x) , m_pCurNode );
896 : }
897 : else
898 : {
899 0 : OString x( s, len );
900 0 : m_pCurData->AddData( helper::UnQuotHTML(x) );
901 :
902 : }
903 0 : }
904 :
905 0 : void SimpleXMLParser::Comment( const XML_Char *data )
906 : {
907 0 : m_pCurData = NULL;
908 0 : new XMLComment( OString( data ), m_pCurNode );
909 0 : }
910 :
911 0 : void SimpleXMLParser::Default( const XML_Char *s, int len )
912 : {
913 0 : m_pCurData = NULL;
914 0 : new XMLDefault(OString( s, len ), m_pCurNode );
915 0 : }
916 :
917 0 : XMLFile *SimpleXMLParser::Execute( const OString &rFileName, XMLFile* pXMLFileIn )
918 : {
919 0 : m_aErrorInformation.m_eCode = XML_ERROR_NONE;
920 0 : m_aErrorInformation.m_nLine = 0;
921 0 : m_aErrorInformation.m_nColumn = 0;
922 0 : m_aErrorInformation.m_sMessage = "ERROR: Unable to open file ";
923 0 : m_aErrorInformation.m_sMessage += rFileName;
924 :
925 0 : OUString aFileURL(lcl_pathnameToAbsoluteUrl(rFileName));
926 :
927 : oslFileHandle h;
928 0 : if (osl_openFile(aFileURL.pData, &h, osl_File_OpenFlag_Read)
929 : != osl_File_E_None)
930 : {
931 0 : return 0;
932 : }
933 :
934 : sal_uInt64 s;
935 0 : oslFileError e = osl_getFileSize(h, &s);
936 0 : void * p = NULL;
937 0 : if (e == osl_File_E_None)
938 : {
939 0 : e = osl_mapFile(h, &p, s, 0, 0);
940 : }
941 0 : if (e != osl_File_E_None)
942 : {
943 0 : osl_closeFile(h);
944 0 : return 0;
945 : }
946 :
947 0 : m_pXMLFile = pXMLFileIn;
948 0 : m_pXMLFile->SetName( rFileName );
949 :
950 0 : m_pCurNode = m_pXMLFile;
951 0 : m_pCurData = NULL;
952 :
953 0 : m_aErrorInformation.m_eCode = XML_ERROR_NONE;
954 0 : m_aErrorInformation.m_nLine = 0;
955 0 : m_aErrorInformation.m_nColumn = 0;
956 0 : if ( !m_pXMLFile->GetName().isEmpty())
957 : {
958 0 : m_aErrorInformation.m_sMessage = "File " + m_pXMLFile->GetName() + " parsed successfully";
959 : }
960 : else
961 0 : m_aErrorInformation.m_sMessage = "XML-File parsed successfully";
962 :
963 0 : if (!XML_Parse(m_aParser, static_cast< char * >(p), s, true))
964 : {
965 0 : m_aErrorInformation.m_eCode = XML_GetErrorCode( m_aParser );
966 0 : m_aErrorInformation.m_nLine = XML_GetErrorLineNumber( m_aParser );
967 0 : m_aErrorInformation.m_nColumn = XML_GetErrorColumnNumber( m_aParser );
968 :
969 0 : m_aErrorInformation.m_sMessage = "ERROR: ";
970 0 : if ( !m_pXMLFile->GetName().isEmpty())
971 0 : m_aErrorInformation.m_sMessage += m_pXMLFile->GetName();
972 : else
973 0 : m_aErrorInformation.m_sMessage += OString( "XML-File (");
974 :
975 0 : m_aErrorInformation.m_sMessage +=
976 0 : OString::number(sal::static_int_cast< sal_Int64 >(m_aErrorInformation.m_nLine)) + "," +
977 0 : OString::number(sal::static_int_cast< sal_Int64 >(m_aErrorInformation.m_nColumn)) + "): ";
978 :
979 0 : switch (m_aErrorInformation.m_eCode)
980 : {
981 : case XML_ERROR_NO_MEMORY:
982 0 : m_aErrorInformation.m_sMessage += "No memory";
983 0 : break;
984 : case XML_ERROR_SYNTAX:
985 0 : m_aErrorInformation.m_sMessage += "Syntax";
986 0 : break;
987 : case XML_ERROR_NO_ELEMENTS:
988 0 : m_aErrorInformation.m_sMessage += "No elements";
989 0 : break;
990 : case XML_ERROR_INVALID_TOKEN:
991 0 : m_aErrorInformation.m_sMessage += "Invalid token";
992 0 : break;
993 : case XML_ERROR_UNCLOSED_TOKEN:
994 0 : m_aErrorInformation.m_sMessage += "Unclosed token";
995 0 : break;
996 : case XML_ERROR_PARTIAL_CHAR:
997 0 : m_aErrorInformation.m_sMessage += "Partial char";
998 0 : break;
999 : case XML_ERROR_TAG_MISMATCH:
1000 0 : m_aErrorInformation.m_sMessage += "Tag mismatch";
1001 0 : break;
1002 : case XML_ERROR_DUPLICATE_ATTRIBUTE:
1003 0 : m_aErrorInformation.m_sMessage += "Dublicat attribute";
1004 0 : break;
1005 : case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
1006 0 : m_aErrorInformation.m_sMessage += "Junk after doc element";
1007 0 : break;
1008 : case XML_ERROR_PARAM_ENTITY_REF:
1009 0 : m_aErrorInformation.m_sMessage += "Param entity ref";
1010 0 : break;
1011 : case XML_ERROR_UNDEFINED_ENTITY:
1012 0 : m_aErrorInformation.m_sMessage += "Undefined entity";
1013 0 : break;
1014 : case XML_ERROR_RECURSIVE_ENTITY_REF:
1015 0 : m_aErrorInformation.m_sMessage += "Recursive entity ref";
1016 0 : break;
1017 : case XML_ERROR_ASYNC_ENTITY:
1018 0 : m_aErrorInformation.m_sMessage += "Async_entity";
1019 0 : break;
1020 : case XML_ERROR_BAD_CHAR_REF:
1021 0 : m_aErrorInformation.m_sMessage += "Bad char ref";
1022 0 : break;
1023 : case XML_ERROR_BINARY_ENTITY_REF:
1024 0 : m_aErrorInformation.m_sMessage += "Binary entity";
1025 0 : break;
1026 : case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
1027 0 : m_aErrorInformation.m_sMessage += "Attribute external entity ref";
1028 0 : break;
1029 : case XML_ERROR_MISPLACED_XML_PI:
1030 0 : m_aErrorInformation.m_sMessage += "Misplaced xml pi";
1031 0 : break;
1032 : case XML_ERROR_UNKNOWN_ENCODING:
1033 0 : m_aErrorInformation.m_sMessage += "Unknown encoding";
1034 0 : break;
1035 : case XML_ERROR_INCORRECT_ENCODING:
1036 0 : m_aErrorInformation.m_sMessage += "Incorrect encoding";
1037 0 : break;
1038 : case XML_ERROR_UNCLOSED_CDATA_SECTION:
1039 0 : m_aErrorInformation.m_sMessage += "Unclosed cdata section";
1040 0 : break;
1041 : case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
1042 0 : m_aErrorInformation.m_sMessage += "External entity handling";
1043 0 : break;
1044 : case XML_ERROR_NOT_STANDALONE:
1045 0 : m_aErrorInformation.m_sMessage += "Not standalone";
1046 0 : break;
1047 : case XML_ERROR_NONE:
1048 0 : break;
1049 : default:
1050 0 : break;
1051 : }
1052 0 : delete m_pXMLFile;
1053 0 : m_pXMLFile = NULL;
1054 : }
1055 :
1056 0 : osl_unmapMappedFile(h, p, s);
1057 0 : osl_closeFile(h);
1058 :
1059 0 : return m_pXMLFile;
1060 : }
1061 :
1062 : namespace
1063 : {
1064 :
1065 0 : static icu::UnicodeString lcl_QuotRange(
1066 : const icu::UnicodeString& rString, const sal_Int32 nStart,
1067 : const sal_Int32 nEnd, bool bInsideTag = false )
1068 : {
1069 0 : icu::UnicodeString sReturn;
1070 : assert( nStart < nEnd );
1071 : assert( nStart >= 0 );
1072 : assert( nEnd <= rString.length() );
1073 0 : for (sal_Int32 i = nStart; i < nEnd; ++i)
1074 : {
1075 0 : switch (rString[i])
1076 : {
1077 : case '<':
1078 0 : sReturn.append("<");
1079 0 : break;
1080 : case '>':
1081 0 : sReturn.append(">");
1082 0 : break;
1083 : case '"':
1084 0 : if( !bInsideTag )
1085 0 : sReturn.append(""");
1086 : else
1087 0 : sReturn.append(rString[i]);
1088 0 : break;
1089 : case '&':
1090 0 : if (rString.startsWith("&", i, 5))
1091 0 : sReturn.append('&');
1092 : else
1093 0 : sReturn.append("&");
1094 0 : break;
1095 : default:
1096 0 : sReturn.append(rString[i]);
1097 0 : break;
1098 : }
1099 : }
1100 0 : return sReturn;
1101 : }
1102 :
1103 0 : static bool lcl_isTag( const icu::UnicodeString& rString )
1104 : {
1105 : static const int nSize = 13;
1106 : static const icu::UnicodeString vTags[nSize] = {
1107 : "ahelp", "link", "item", "emph", "defaultinline",
1108 : "switchinline", "caseinline", "variable",
1109 0 : "bookmark_value", "image", "embedvar", "alt", "sup" };
1110 :
1111 0 : for( int nIndex = 0; nIndex < nSize; ++nIndex )
1112 : {
1113 0 : if( rString.startsWith("<" + vTags[nIndex]) ||
1114 0 : rString == "</" + vTags[nIndex] + ">" )
1115 0 : return true;
1116 : }
1117 :
1118 0 : return rString == "<br/>" || rString =="<help-id-missing/>";
1119 : }
1120 :
1121 : } /// anonymous namespace
1122 :
1123 0 : OString XMLUtil::QuotHTML( const OString &rString )
1124 : {
1125 0 : if( rString.trim().isEmpty() )
1126 0 : return rString;
1127 0 : UErrorCode nIcuErr = U_ZERO_ERROR;
1128 : static const sal_uInt32 nSearchFlags =
1129 : UREGEX_DOTALL | UREGEX_CASE_INSENSITIVE;
1130 : static const OUString sPattern(
1131 0 : "<[/]\?\?[a-z_-]+?(?:| +[a-z]+?=\".*?\") *[/]\?\?>");
1132 : static const UnicodeString sSearchPat(
1133 0 : reinterpret_cast<const UChar*>(sPattern.getStr()),
1134 0 : sPattern.getLength() );
1135 :
1136 0 : const OUString sOUSource = OStringToOUString(rString, RTL_TEXTENCODING_UTF8);
1137 : icu::UnicodeString sSource(
1138 : reinterpret_cast<const UChar*>(
1139 0 : sOUSource.getStr()), sOUSource.getLength() );
1140 :
1141 0 : RegexMatcher aRegexMatcher( sSearchPat, nSearchFlags, nIcuErr );
1142 0 : aRegexMatcher.reset( sSource );
1143 :
1144 0 : icu::UnicodeString sReturn;
1145 0 : int32_t nEndPos = 0;
1146 0 : int32_t nStartPos = 0;
1147 0 : while( aRegexMatcher.find(nStartPos, nIcuErr) && nIcuErr == U_ZERO_ERROR )
1148 : {
1149 0 : nStartPos = aRegexMatcher.start(nIcuErr);
1150 0 : if ( nEndPos < nStartPos )
1151 0 : sReturn.append(lcl_QuotRange(sSource, nEndPos, nStartPos));
1152 0 : nEndPos = aRegexMatcher.end(nIcuErr);
1153 0 : icu::UnicodeString sMatch = aRegexMatcher.group(nIcuErr);
1154 0 : if( lcl_isTag(sMatch) )
1155 : {
1156 0 : sReturn.append("<");
1157 0 : sReturn.append(lcl_QuotRange(sSource, nStartPos+1, nEndPos-1, true));
1158 0 : sReturn.append(">");
1159 : }
1160 : else
1161 0 : sReturn.append(lcl_QuotRange(sSource, nStartPos, nEndPos));
1162 0 : ++nStartPos;
1163 0 : }
1164 0 : if( nEndPos < sSource.length() )
1165 0 : sReturn.append(lcl_QuotRange(sSource, nEndPos, sSource.length()));
1166 0 : sReturn.append('\0');
1167 : return
1168 : OUStringToOString(
1169 0 : OUString(reinterpret_cast<const sal_Unicode*>(sReturn.getBuffer())),
1170 0 : RTL_TEXTENCODING_UTF8);
1171 0 : }
1172 :
1173 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|