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