1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 10 * OpenOffice.org is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License version 3 12 * only, as published by the Free Software Foundation. 13 * 14 * OpenOffice.org is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License version 3 for more details 18 * (a copy is included in the LICENSE file that accompanied this code). 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * version 3 along with OpenOffice.org. If not, see 22 * <http://www.openoffice.org/license.html> 23 * for a copy of the LGPLv3 License. 24 * 25 ************************************************************************/ 26 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_extensions.hxx" 30 31 #include "soaprequest.hxx" 32 #include "errormail.hxx" 33 #include "config.hxx" 34 #include <boost/shared_ptr.hpp> 35 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 36 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 37 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 38 #include <rtl/strbuf.hxx> 39 #include <rtl/ustring.hxx> 40 41 42 using namespace com::sun::star::uno; 43 using namespace com::sun::star::lang; 44 using namespace com::sun::star::io; 45 using boost::shared_ptr; 46 using com::sun::star::io::XOutputStream; 47 using com::sun::star::ucb::XSimpleFileAccess; 48 using rtl::OUString; 49 using rtl::OString; 50 using rtl::OStringBuffer; 51 52 53 namespace 54 { 55 static unsigned long asUlong(sal_Int8 input) 56 { 57 return *reinterpret_cast<unsigned char *>(&input); 58 }; 59 60 static Sequence<sal_Int8> base64_encode(const Sequence<sal_Int8>& input) 61 { 62 static const char base64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 63 Sequence<sal_Int8> result(4); 64 unsigned long value = asUlong(input[0]) << 16; 65 if(input.getLength() > 1) value |= asUlong(input[1]) << 8; 66 if(input.getLength() > 2) value |= asUlong(input[2]); 67 68 result[0] = static_cast<sal_Int8>(base64_tab[(value >> 18) & 0x3F]); 69 result[1] = static_cast<sal_Int8>(base64_tab[(value >> 12) & 0x3F]); 70 result[2] = static_cast<sal_Int8>('='); 71 result[3] = static_cast<sal_Int8>('='); 72 73 if (input.getLength() > 1) 74 { 75 result[2] = base64_tab[(value >> 6) & 0x3F]; 76 if (input.getLength() > 2) 77 result[3] = base64_tab[(value >> 0) & 0x3F]; 78 } 79 return result; 80 }; 81 82 static OString replaceAll(const OString& str, sal_Char old, const OString& replacement) 83 { 84 OStringBuffer result; 85 sal_Int32 idx = 0; 86 do { 87 result.append(str.getToken(0, old, idx)); 88 if(idx>=0) result.append(replacement); 89 } while(idx >= 0); 90 return result.makeStringAndClear(); 91 }; 92 93 static OString xmlEncode(const OString& input) 94 { 95 OString result = replaceAll(input, '&', OString("&")); 96 result = replaceAll(result, '<', OString("<")); 97 return replaceAll(result, '>', OString(">")); 98 } 99 100 static shared_ptr<Sequence<sal_Int8> > createSequenceFromString(const OString& str) 101 { 102 const sal_Int32 size = str.getLength(); 103 shared_ptr<Sequence<sal_Int8> > result(new Sequence<sal_Int8>(size)); 104 for(sal_Int32 idx=0; idx < size; idx++) 105 (*result)[idx] = str[idx]; 106 return result; 107 }; 108 109 static void writeString(const Reference<XOutputStream>& target, const OString& str) 110 { 111 shared_ptr<Sequence<sal_Int8> > seq = createSequenceFromString(str); 112 target->writeBytes(*seq); 113 }; 114 115 static void writeFile(const Reference<XMultiServiceFactory>& sf, const Reference<XOutputStream>& target, const OUString& fileurl) 116 { 117 Reference<XSimpleFileAccess> file_access( 118 sf->createInstance(OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess")), 119 UNO_QUERY); 120 Reference<XInputStream> file = file_access->openFileRead(fileurl); 121 const sal_Int32 bufsize = 3; 122 sal_Int32 bytes_read; 123 Sequence<sal_Int8> buf(bufsize); 124 do 125 { 126 bytes_read = file->readBytes(buf, bufsize); 127 if(bytes_read < buf.getLength()) buf.realloc(bytes_read); 128 if(bytes_read) target->writeBytes(base64_encode(buf)); 129 } while(bytes_read == bufsize); 130 }; 131 132 static const OString SOAP_START( 133 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 134 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" 135 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n" 136 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n" 137 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n" 138 "xmlns:rds=\"urn:ReportDataService\"\n" 139 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n" 140 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 141 "<SOAP-ENV:Body>\n" 142 "<rds:submitReport>\n"); 143 static const OString SOAP_ITEMS_START("<hash xsi:type=\"apache:Map\">\n"); 144 static const OString SOAP_ITEMS_END("</hash>\n"); 145 static const OString SOAP_END( 146 "</rds:submitReport>\n" 147 "</SOAP-ENV:Body>\n" 148 "</SOAP-ENV:Envelope>\n"); 149 static const OString SOAP_ITEM_END("]]></value></item>\n"); 150 151 static const OString getSoapOfficeversion(const Reference<XMultiServiceFactory>& sf) 152 { 153 return ::rtl::OUStringToOString(oooimprovement::Config(sf).getCompleteProductname(), RTL_TEXTENCODING_ASCII_US); 154 }; 155 156 static const OString getSoapSoapId(const Reference<XMultiServiceFactory>& sf, const OString& soap_id) 157 { 158 OStringBuffer buf; 159 buf.append("<body xsi:type=\"xsd:string\">"); 160 buf.append(xmlEncode(soap_id)).append("\n"); 161 buf.append(xmlEncode(getSoapOfficeversion(sf))).append("\n"); 162 buf.append("</body>\n"); 163 return buf.makeStringAndClear(); 164 }; 165 166 static const OString getSoapItemStart(const OString& key) 167 { 168 OStringBuffer buf = 169 "<item>\n" 170 "<key xsi:type=\"xsd:string\">" + key + "</key>\n" 171 "<value xsi:type=\"xsd:string\"><![CDATA["; 172 return buf.makeStringAndClear(); 173 }; 174 } 175 176 namespace oooimprovement 177 { 178 SoapRequest::SoapRequest(const Reference<XMultiServiceFactory>& sf, const OUString& soap_id, const OUString& logfile) 179 : m_ServiceFactory(sf) 180 , m_SoapId(soap_id) 181 , m_Logfile(logfile) 182 {} 183 184 void SoapRequest::writeTo(const Reference<XOutputStream>& target) const 185 { 186 writeString(target, SOAP_START); 187 writeString( 188 target, 189 getSoapSoapId(m_ServiceFactory, rtl::OUStringToOString(m_SoapId, RTL_TEXTENCODING_ASCII_US))); 190 writeString(target, SOAP_ITEMS_START); 191 writeString(target, getSoapItemStart("reportmail.xml")); 192 writeString(target, Errormail(m_ServiceFactory).getXml()); 193 writeString(target, SOAP_ITEM_END); 194 writeString(target, getSoapItemStart("data.zip")); 195 writeFile(m_ServiceFactory, target, m_Logfile); 196 writeString(target, SOAP_ITEM_END); 197 writeString(target, SOAP_ITEMS_END); 198 writeString(target, SOAP_END); 199 } 200 } 201