1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <fstream>
25 #include <string.h>
26 #include <resourcemodel/TagLogger.hxx>
27 #include <resourcemodel/util.hxx>
28 #include <resourcemodel/QNameToString.hxx>
29 
30 namespace writerfilter
31 {
32 XMLTag::Pointer_t XMLTag::NIL(new XMLTag("NIL"));
33 
addAttr(string sName,string sValue)34 void XMLTag::addAttr(string sName, string sValue)
35 {
36     XMLAttribute aAttr(sName, sValue);
37 
38     mAttrs.push_back(aAttr);
39 }
40 
addAttr(string sName,const::rtl::OUString & sValue)41 void XMLTag::addAttr(string sName, const ::rtl::OUString & sValue)
42 {
43     addAttr(sName,
44             OUStringToOString
45             (sValue, RTL_TEXTENCODING_ASCII_US).getStr());
46 }
47 
addAttr(string sName,sal_uInt32 nValue)48 void XMLTag::addAttr(string sName, sal_uInt32 nValue)
49 {
50     static char buffer[256];
51     snprintf(buffer, sizeof(buffer), "%" SAL_PRIdINT32, nValue);
52     addAttr(sName, buffer);
53 }
54 
addAttr(string sName,uno::Any aAny)55 void XMLTag::addAttr(string sName, uno::Any aAny)
56 {
57     string aTmpStrInt;
58     string aTmpStrFloat;
59     string aTmpStrString;
60 
61     static char buffer[256];
62 
63     try
64     {
65         sal_Int32 nInt = 0;
66         aAny >>= nInt;
67 
68         snprintf(buffer, sizeof(buffer), "%" SAL_PRIdINT32,
69                  nInt);
70 
71         aTmpStrInt = buffer;
72     }
73     catch (uno::Exception aExcept)
74     {
75         aTmpStrInt = "exception";
76     }
77 
78     try
79     {
80         float nFloat = 0.0;
81         aAny >>= nFloat;
82 
83         snprintf(buffer, sizeof(buffer), "%f",
84                  nFloat);
85 
86         aTmpStrFloat = buffer;
87     }
88     catch (uno::Exception aExcept)
89     {
90         aTmpStrFloat = "exception";
91     }
92 
93     try
94     {
95         ::rtl::OUString aStr;
96         aAny >>= aStr;
97 
98         aTmpStrString = OUStringToOString(aStr, RTL_TEXTENCODING_ASCII_US).getStr();
99     }
100     catch (uno::Exception aExcept)
101     {
102         aTmpStrString = "exception";
103     }
104 
105     addAttr(sName, "i:" + aTmpStrInt + " f:" + aTmpStrFloat + " s:" +
106             aTmpStrString);
107 }
108 
addTag(XMLTag::Pointer_t pTag)109 void XMLTag::addTag(XMLTag::Pointer_t pTag)
110 {
111     if (pTag != XMLTag::Pointer_t())
112         mTags.push_back(pTag);
113 }
114 
chars(const string & rChars)115 void XMLTag::chars(const string & rChars)
116 {
117     mChars += rChars;
118 }
119 
chars(const::rtl::OUString & rChars)120 void XMLTag::chars(const ::rtl::OUString & rChars)
121 {
122     chars(OUStringToOString(rChars, RTL_TEXTENCODING_ASCII_US).getStr());
123 }
124 
getTag() const125 const string & XMLTag::getTag() const
126 {
127     return mTag;
128 }
129 
toString() const130 string XMLTag::toString() const
131 {
132     if (mChars.length() > 0)
133         return mChars;
134 
135     string sResult;
136 
137     if (mMode == START || mMode == COMPLETE)
138     {
139         sResult += "<" + mTag;
140 
141         XMLAttributes_t::const_iterator aIt = mAttrs.begin();
142         while (aIt != mAttrs.end())
143         {
144             sResult += " ";
145             sResult += aIt->mName;
146             sResult += "=\"";
147             sResult += xmlify(aIt->mValue);
148             sResult += "\"";
149 
150             aIt++;
151         }
152 
153         sResult +=">";
154 
155         if (mTags.size() > 0)
156         {
157             XMLTags_t::const_iterator aItTags = mTags.begin();
158             while (aItTags != mTags.end())
159             {
160                 if ((*aItTags).get() != NULL)
161                     sResult += (*aItTags)->toString();
162 
163                 aItTags++;
164             }
165         }
166     }
167 
168     if (mMode == END || mMode == COMPLETE)
169         sResult += "</" + mTag + ">";
170 
171     return sResult;
172 }
173 
toTree(const string & sIndent) const174 string XMLTag::toTree(const string & sIndent) const
175 {
176     if (mChars.length() > 0)
177         return sIndent + mChars;
178 
179     string sResult;
180 
181     {
182         size_t nSize = sIndent.size();
183         if (nSize > 1)
184         {
185             sResult += sIndent.substr(0, nSize - 2) + "+-\\" + mTag;
186         }
187         else
188         {
189             sResult += "\\" + mTag;
190         }
191     }
192 
193     XMLAttributes_t::const_iterator aIt = mAttrs.begin();
194     while (aIt != mAttrs.end())
195     {
196         if (aIt == mAttrs.begin())
197         {
198             sResult += "(";
199         }
200         else
201         {
202             sResult += sIndent + ", ";
203         }
204 
205         sResult += aIt->mName;
206         sResult += "=";
207         sResult += aIt->mValue;
208 
209         aIt++;
210 
211         if (aIt == mAttrs.end())
212         {
213             sResult += ")";
214         }
215     }
216 
217     sResult += "\n";
218 
219     if (mTags.size() > 0)
220     {
221         XMLTags_t::const_iterator aItTags = mTags.begin();
222         size_t nSize = mTags.size();
223         while (aItTags != mTags.end())
224         {
225             if ((*aItTags).get() != NULL)
226             {
227                 if (nSize == 1)
228                 {
229                     sResult += (*aItTags)->toTree(sIndent + "  ");
230                 }
231                 else
232                 {
233                     sResult += (*aItTags)->toTree(sIndent + "| ");
234                 }
235             }
236 
237             aItTags++;
238             nSize--;
239         }
240     }
241 
242     return sResult;
243 }
244 
output(ostream & o,const string & sIndent) const245 ostream & XMLTag::output(ostream & o, const string & sIndent) const
246 {
247     bool bHasContent = mChars.size() > 0 || mTags.size() > 0;
248 
249     if (mMode == START || mMode == COMPLETE)
250     {
251         o << sIndent << "<" << mTag;
252 
253         XMLAttributes_t::const_iterator aItAttrs(mAttrs.begin());
254         while (aItAttrs != mAttrs.end())
255         {
256             o << " " << aItAttrs->mName << "=\""
257               << xmlify(aItAttrs->mValue)
258               << "\"";
259 
260             aItAttrs++;
261         }
262 
263         if (bHasContent)
264         {
265             o << ">";
266 
267             string sNewIndent = sIndent + "  ";
268             XMLTags_t::const_iterator aItTags(mTags.begin());
269             while (aItTags != mTags.end())
270             {
271                 if (aItTags == mTags.begin())
272                     o << endl;
273 
274                 (*aItTags)->output(o, sNewIndent);
275                 aItTags++;
276             }
277 
278             o << mChars;
279         }
280     }
281 
282     if (mMode == END || mMode == COMPLETE)
283     {
284         if (bHasContent)
285         {
286             if (mTags.size() > 0)
287                 o << sIndent;
288 
289             o << "</" << mTag << ">" << endl;
290         }
291         else
292             o << "/>" << endl;
293     }
294 
295     return o;
296 }
297 
298 typedef hash_map< const char*, TagLogger::Pointer_t, rtl::CStringHash, rtl::CStringEqual> TagLoggerHashMap_t;
299 static TagLoggerHashMap_t * tagLoggers = NULL;
300 
TagLogger()301 TagLogger::TagLogger()
302 : mFileName("writerfilter")
303 {
304 }
305 
~TagLogger()306 TagLogger::~TagLogger()
307 {
308 }
309 
setFileName(const string & rName)310 void TagLogger::setFileName(const string & rName)
311 {
312     mFileName = rName;
313 }
314 
getInstance(const char * name)315 TagLogger::Pointer_t TagLogger::getInstance(const char * name)
316 {
317     if (tagLoggers == NULL)
318         tagLoggers = new TagLoggerHashMap_t();
319 
320     TagLoggerHashMap_t::iterator aIt = tagLoggers->end();
321 
322     if (! tagLoggers->empty())
323         aIt = tagLoggers->find(name);
324 
325     if (aIt == tagLoggers->end())
326     {
327         TagLogger::Pointer_t pTagLogger(new TagLogger());
328         pair<const char *, TagLogger::Pointer_t> entry(name, pTagLogger);
329         aIt = tagLoggers->insert(entry).first;
330     }
331 
332     return aIt->second;
333 }
334 
currentTag() const335 XMLTag::Pointer_t TagLogger::currentTag() const
336 {
337     bool bEmpty=mTags.empty();
338     if (!bEmpty)
339         return mTags.top();
340 
341     return XMLTag::NIL;
342 }
343 
startDocument()344 void TagLogger::startDocument()
345 {
346     XMLTag::Pointer_t pTag(new XMLTag("root"));
347     mTags.push(pTag);
348     mpRoot = pTag;
349 }
350 
element(const string & name)351 void TagLogger::element(const string & name)
352 {
353     startElement(name);
354     endElement(name);
355 }
356 
startElement(const string & name)357 void TagLogger::startElement(const string & name)
358 {
359     XMLTag::Pointer_t pTag(new XMLTag(name));
360     currentTag()->addTag(pTag);
361     mTags.push(pTag);
362 }
363 
attribute(const string & name,const string & value)364 void TagLogger::attribute(const string & name, const string & value)
365 {
366     currentTag()->addAttr(name, value);
367 }
368 
attribute(const string & name,const::rtl::OUString & value)369 void TagLogger::attribute(const string & name, const ::rtl::OUString & value)
370 {
371     currentTag()->addAttr(name, value);
372 }
373 
attribute(const string & name,sal_uInt32 value)374 void TagLogger::attribute(const string & name, sal_uInt32 value)
375 {
376     currentTag()->addAttr(name, value);
377 }
378 
attribute(const string & name,const uno::Any aAny)379 void TagLogger::attribute(const string & name, const uno::Any aAny)
380 {
381     currentTag()->addAttr(name, aAny);
382 }
383 
addTag(XMLTag::Pointer_t pTag)384 void TagLogger::addTag(XMLTag::Pointer_t pTag)
385 {
386     currentTag()->addTag(pTag);
387 }
388 
chars(const string & rChars)389 void TagLogger::chars(const string & rChars)
390 {
391     currentTag()->chars(xmlify(rChars));
392 }
393 
chars(const::rtl::OUString & rChars)394 void TagLogger::chars(const ::rtl::OUString & rChars)
395 {
396     chars(OUStringToOString(rChars, RTL_TEXTENCODING_ASCII_US).getStr());
397 }
398 
endElement(const string & name)399 void TagLogger::endElement(const string & name)
400 {
401     string nameRemoved = currentTag()->getTag();
402 
403     if (name == nameRemoved)
404         mTags.pop();
405     else {
406         XMLTag::Pointer_t pTag(new XMLTag("end.mismatch"));
407         pTag->addAttr("name", name);
408         pTag->addAttr("top", nameRemoved);
409 
410         currentTag()->addTag(pTag);
411     }
412 
413 }
414 
endDocument()415 void TagLogger::endDocument()
416 {
417     mTags.pop();
418 }
419 
output(ostream & o) const420 ostream & TagLogger::output(ostream & o) const
421 {
422     return mpRoot->output(o);
423 }
424 
dump(const char * name)425 void TagLogger::dump(const char * name)
426 {
427     TagLoggerHashMap_t::iterator aIt(tagLoggers->find(name));
428     if (aIt != tagLoggers->end())
429     {
430         string fileName;
431         char * temp = getenv("TAGLOGGERTMP");
432 
433         if (temp != NULL)
434             fileName += temp;
435         else
436             fileName += "/tmp";
437 
438         string sPrefix = aIt->second->mFileName;
439         size_t nLastSlash = sPrefix.find_last_of('/');
440         size_t nLastBackslash = sPrefix.find_last_of('\\');
441         size_t nCutPos = nLastSlash;
442         if (nLastBackslash < nCutPos)
443             nCutPos = nLastBackslash;
444         if (nCutPos < sPrefix.size())
445             sPrefix = sPrefix.substr(nCutPos + 1);
446 
447         fileName += "/";
448         fileName += sPrefix;
449         fileName +=".";
450         fileName += name;
451         fileName += ".xml";
452 
453         ofstream dumpStream(fileName.c_str());
454         aIt->second->output(dumpStream);
455     }
456 }
457 
PropertySetToTagHandler(IdToString::Pointer_t pIdToString)458 PropertySetToTagHandler::PropertySetToTagHandler(IdToString::Pointer_t pIdToString)
459   : mpTag(new XMLTag("propertyset")), mpIdToString(pIdToString)
460 {
461 }
462 
~PropertySetToTagHandler()463 PropertySetToTagHandler::~PropertySetToTagHandler()
464 {
465 }
466 
resolve(XMLTag & rTag,writerfilter::Reference<Properties>::Pointer_t pProps)467 void PropertySetToTagHandler::resolve
468 (XMLTag & rTag, writerfilter::Reference<Properties>::Pointer_t pProps)
469 {
470     if (pProps.get() != NULL)
471     {
472         PropertySetToTagHandler aHandler(mpIdToString);
473         pProps->resolve(aHandler);
474         rTag.addTag(aHandler.getTag());
475     }
476 }
477 
attribute(Id name,Value & val)478 void PropertySetToTagHandler::attribute(Id name, Value & val)
479 {
480     XMLTag::Pointer_t pTag(new XMLTag("attribute"));
481 
482     pTag->addAttr("name", (*QNameToString::Instance())(name));
483     pTag->addAttr("value", val.toString());
484 
485     resolve(*pTag, val.getProperties());
486 
487     mpTag->addTag(pTag);
488 }
489 
sprm(Sprm & rSprm)490 void PropertySetToTagHandler::sprm(Sprm & rSprm)
491 {
492     XMLTag::Pointer_t pTag(new XMLTag("sprm"));
493 
494     string sName;
495 
496     if (mpIdToString != IdToString::Pointer_t())
497         sName = mpIdToString->toString(rSprm.getId());
498 
499     pTag->addAttr("name", sName);
500 
501     static char sBuffer[256];
502     snprintf(sBuffer, sizeof(sBuffer),
503              "0x%" SAL_PRIxUINT32 ", %" SAL_PRIuUINT32, rSprm.getId(),
504              rSprm.getId());
505     pTag->addAttr("id", sBuffer);
506     pTag->addAttr("value", rSprm.getValue()->toString());
507 
508     resolve(*pTag, rSprm.getProps());
509 
510     mpTag->addTag(pTag);
511 }
512 
513 
unoPropertySetToTag(uno::Reference<beans::XPropertySet> rPropSet)514 XMLTag::Pointer_t unoPropertySetToTag(uno::Reference<beans::XPropertySet> rPropSet)
515 {
516     uno::Reference<beans::XPropertySetInfo> xPropSetInfo(rPropSet->getPropertySetInfo());
517     uno::Sequence<beans::Property> aProps(xPropSetInfo->getProperties());
518 
519     XMLTag::Pointer_t pResult(new XMLTag("unoPropertySet"));
520 
521     for (int i = 0; i < aProps.getLength(); ++i)
522     {
523         XMLTag::Pointer_t pPropTag(new XMLTag("property"));
524 
525         ::rtl::OUString sName(aProps[i].Name);
526 
527         pPropTag->addAttr("name", sName);
528         try
529         {
530             pPropTag->addAttr("value", rPropSet->getPropertyValue(sName));
531         }
532         catch (uno::Exception aException)
533         {
534             XMLTag::Pointer_t pException(new XMLTag("exception"));
535 
536             pException->chars("getPropertyValue(\"");
537             pException->chars(sName);
538             pException->chars("\")");
539             pPropTag->addTag(pException);
540         }
541 
542         pResult->addTag(pPropTag);
543     }
544 
545     return pResult;
546 }
547 
548 }
549