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