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("&")); 93 result = replaceAll(result, '<', OString("<")); 94 return replaceAll(result, '>', OString(">")); 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