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 
25 // MARKER(update_precomp.py): autogen include statement, do not remove
26 #include "precompiled_extensions.hxx"
27 
28 #include "soaprequest.hxx"
29 #include "errormail.hxx"
30 #include "config.hxx"
31 #include <boost/shared_ptr.hpp>
32 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
35 #include <rtl/strbuf.hxx>
36 #include <rtl/ustring.hxx>
37 
38 
39 using namespace com::sun::star::uno;
40 using namespace com::sun::star::lang;
41 using namespace com::sun::star::io;
42 using boost::shared_ptr;
43 using com::sun::star::io::XOutputStream;
44 using com::sun::star::ucb::XSimpleFileAccess;
45 using rtl::OUString;
46 using rtl::OString;
47 using rtl::OStringBuffer;
48 
49 
50 namespace
51 {
asUlong(sal_Int8 input)52     static unsigned long asUlong(sal_Int8 input)
53     {
54         return *reinterpret_cast<unsigned char *>(&input);
55     };
56 
base64_encode(const Sequence<sal_Int8> & input)57     static Sequence<sal_Int8> base64_encode(const Sequence<sal_Int8>& input)
58     {
59         static const char base64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
60         Sequence<sal_Int8> result(4);
61         unsigned long value = asUlong(input[0]) << 16;
62         if(input.getLength() > 1) value |= asUlong(input[1]) << 8;
63         if(input.getLength() > 2) value |= asUlong(input[2]);
64 
65         result[0] = static_cast<sal_Int8>(base64_tab[(value >> 18) & 0x3F]);
66         result[1] = static_cast<sal_Int8>(base64_tab[(value >> 12) & 0x3F]);
67         result[2] = static_cast<sal_Int8>('=');
68         result[3] = static_cast<sal_Int8>('=');
69 
70         if (input.getLength() > 1)
71         {
72             result[2] = base64_tab[(value >> 6) & 0x3F];
73             if (input.getLength() > 2)
74                  result[3] = base64_tab[(value >> 0) & 0x3F];
75         }
76         return result;
77     };
78 
replaceAll(const OString & str,sal_Char old,const OString & replacement)79     static OString replaceAll(const OString& str, sal_Char old, const OString& replacement)
80     {
81         OStringBuffer result;
82         sal_Int32 idx = 0;
83         do {
84             result.append(str.getToken(0, old, idx));
85             if(idx>=0) result.append(replacement);
86         } while(idx >= 0);
87         return result.makeStringAndClear();
88     };
89 
xmlEncode(const OString & input)90     static OString xmlEncode(const OString& input)
91     {
92         OString result = replaceAll(input, '&', OString("&amp;"));
93         result = replaceAll(result, '<', OString("&lt;"));
94         return replaceAll(result, '>', OString("&gt;"));
95     }
96 
createSequenceFromString(const OString & str)97     static shared_ptr<Sequence<sal_Int8> > createSequenceFromString(const OString& str)
98     {
99         const sal_Int32 size = str.getLength();
100         shared_ptr<Sequence<sal_Int8> > result(new Sequence<sal_Int8>(size));
101         for(sal_Int32 idx=0; idx < size; idx++)
102             (*result)[idx] = str[idx];
103         return result;
104     };
105 
writeString(const Reference<XOutputStream> & target,const OString & str)106     static void writeString(const Reference<XOutputStream>& target, const OString& str)
107     {
108         shared_ptr<Sequence<sal_Int8> > seq = createSequenceFromString(str);
109         target->writeBytes(*seq);
110     };
111 
writeFile(const Reference<XMultiServiceFactory> & sf,const Reference<XOutputStream> & target,const OUString & fileurl)112     static void writeFile(const Reference<XMultiServiceFactory>& sf, const Reference<XOutputStream>& target, const OUString& fileurl)
113     {
114         Reference<XSimpleFileAccess> file_access(
115             sf->createInstance(OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess")),
116             UNO_QUERY);
117         Reference<XInputStream> file = file_access->openFileRead(fileurl);
118         const sal_Int32 bufsize = 3;
119         sal_Int32 bytes_read;
120         Sequence<sal_Int8> buf(bufsize);
121         do
122         {
123             bytes_read = file->readBytes(buf, bufsize);
124             if(bytes_read < buf.getLength()) buf.realloc(bytes_read);
125             if(bytes_read) target->writeBytes(base64_encode(buf));
126         } while(bytes_read == bufsize);
127     };
128 
129     static const OString SOAP_START(
130         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
131         "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
132         "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
133         "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
134         "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
135         "xmlns:rds=\"urn:ReportDataService\"\n"
136         "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
137         "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
138         "<SOAP-ENV:Body>\n"
139         "<rds:submitReport>\n");
140     static const OString SOAP_ITEMS_START("<hash xsi:type=\"apache:Map\">\n");
141     static const OString SOAP_ITEMS_END("</hash>\n");
142     static const OString SOAP_END(
143         "</rds:submitReport>\n"
144         "</SOAP-ENV:Body>\n"
145         "</SOAP-ENV:Envelope>\n");
146     static const OString SOAP_ITEM_END("]]></value></item>\n");
147 
getSoapOfficeversion(const Reference<XMultiServiceFactory> & sf)148     static const OString getSoapOfficeversion(const Reference<XMultiServiceFactory>& sf)
149     {
150         return ::rtl::OUStringToOString(oooimprovement::Config(sf).getCompleteProductname(), RTL_TEXTENCODING_ASCII_US);
151     };
152 
getSoapSoapId(const Reference<XMultiServiceFactory> & sf,const OString & soap_id)153     static const OString getSoapSoapId(const Reference<XMultiServiceFactory>& sf, const OString& soap_id)
154     {
155         OStringBuffer buf;
156         buf.append("<body xsi:type=\"xsd:string\">");
157         buf.append(xmlEncode(soap_id)).append("\n");
158         buf.append(xmlEncode(getSoapOfficeversion(sf))).append("\n");
159         buf.append("</body>\n");
160         return buf.makeStringAndClear();
161     };
162 
getSoapItemStart(const OString & key)163     static const OString getSoapItemStart(const OString& key)
164     {
165         OStringBuffer buf =
166             "<item>\n"
167             "<key xsi:type=\"xsd:string\">" + key + "</key>\n"
168             "<value xsi:type=\"xsd:string\"><![CDATA[";
169         return buf.makeStringAndClear();
170     };
171 }
172 
173 namespace oooimprovement
174 {
SoapRequest(const Reference<XMultiServiceFactory> & sf,const OUString & soap_id,const OUString & logfile)175     SoapRequest::SoapRequest(const Reference<XMultiServiceFactory>& sf, const OUString& soap_id, const OUString& logfile)
176         : m_ServiceFactory(sf)
177         , m_SoapId(soap_id)
178         , m_Logfile(logfile)
179     {}
180 
writeTo(const Reference<XOutputStream> & target) const181      void SoapRequest::writeTo(const Reference<XOutputStream>& target) const
182     {
183         writeString(target, SOAP_START);
184             writeString(
185                 target,
186                 getSoapSoapId(m_ServiceFactory, rtl::OUStringToOString(m_SoapId, RTL_TEXTENCODING_ASCII_US)));
187             writeString(target, SOAP_ITEMS_START);
188                 writeString(target, getSoapItemStart("reportmail.xml"));
189                     writeString(target, Errormail(m_ServiceFactory).getXml());
190                 writeString(target, SOAP_ITEM_END);
191                 writeString(target, getSoapItemStart("data.zip"));
192                     writeFile(m_ServiceFactory, target, m_Logfile);
193                 writeString(target, SOAP_ITEM_END);
194             writeString(target, SOAP_ITEMS_END);
195         writeString(target, SOAP_END);
196     }
197 }
198