1 // FlatMessageIO.cpp 2 // e.moon 6jul99 3 4 #include "FlatMessageIO.h" 5 //#include "xml_export_utils.h" 6 7 #include "ExportContext.h" 8 9 #include <Debug.h> 10 11 // base64 encoding tools 12 #include <E-mail.h> 13 14 #include <cstdlib> 15 #include <cstring> 16 17 __USE_CORTEX_NAMESPACE 18 19 // -------------------------------------------------------- // 20 // *** constants 21 // -------------------------------------------------------- // 22 23 const char* const FlatMessageIO::s_element = "flat-BMessage"; 24 25 // -------------------------------------------------------- // 26 // *** ctor/dtor/accessor 27 // -------------------------------------------------------- // 28 29 FlatMessageIO::~FlatMessageIO() { 30 if(m_ownMessage && m_message) 31 delete m_message; 32 } 33 FlatMessageIO::FlatMessageIO() : 34 m_ownMessage(true), 35 m_message(0) {} 36 FlatMessageIO::FlatMessageIO(const BMessage* message) : 37 m_ownMessage(false), 38 m_message(const_cast<BMessage*>(message)) {} 39 40 void FlatMessageIO::setMessage(BMessage* message) { 41 if(m_ownMessage && m_message) 42 delete m_message; 43 m_ownMessage = false; 44 m_message = message; 45 } 46 47 // -------------------------------------------------------- // 48 // *** static setup method 49 // -------------------------------------------------------- // 50 51 // call this method to install hooks for the tags needed by 52 // FlatMessageIO into the given document type 53 /*static*/ 54 void FlatMessageIO::AddTo(XML::DocumentType* pDocType) { 55 pDocType->addMapping(new Mapping<FlatMessageIO>(s_element)); 56 } 57 58 // -------------------------------------------------------- // 59 // *** IPersistent impl. 60 // -------------------------------------------------------- // 61 62 63 void FlatMessageIO::xmlExportBegin( 64 ExportContext& context) const { 65 66 context.beginElement(s_element); 67 } 68 69 void FlatMessageIO::xmlExportAttributes( 70 ExportContext& context) const { 71 72 context.writeAttr("encoding", "base64"); 73 } 74 75 void FlatMessageIO::xmlExportContent( 76 ExportContext& context) const { 77 78 context.beginContent(); 79 80 // convert message to base64 81 ASSERT(m_message); 82 ssize_t flatSize = m_message->FlattenedSize(); 83 ASSERT(flatSize); 84 char* flatData = new char[flatSize]; 85 status_t err = m_message->Flatten(flatData, flatSize); 86 ASSERT(err == B_OK); 87 88 // make plenty of room for encoded content (encode_base64 adds newlines) 89 ssize_t base64Size = ((flatSize * 3) / 2); 90 char* base64Data = new char[base64Size]; 91 ssize_t base64Used = encode_base64(base64Data, flatData, flatSize); 92 base64Data[base64Used] = '\0'; 93 94 // write the data 95 96 const char* pos = base64Data; 97 while(*pos) { 98 ssize_t chunk = 0; 99 const char* nextBreak = strchr(pos, '\n'); 100 if(!nextBreak) 101 chunk = strlen(pos); 102 else 103 chunk = nextBreak - pos; 104 105 context.writeString(context.indentString()); 106 context.writeString(pos, chunk); 107 context.writeString("\n"); 108 109 pos += chunk; 110 if(*pos == '\n') 111 ++pos; 112 } 113 114 // clean up 115 delete [] flatData; 116 delete [] base64Data; 117 } 118 119 void FlatMessageIO::xmlExportEnd( 120 ExportContext& context) const { 121 context.endElement(); 122 } 123 124 // -------------------------------------------------------- // 125 126 void FlatMessageIO::xmlImportBegin( 127 ImportContext& context) { 128 129 m_base64Data = ""; 130 } 131 132 void FlatMessageIO::xmlImportAttribute( 133 const char* key, 134 const char* value, 135 ImportContext& context) { 136 if(!strcmp(key, "encoding")) { 137 if(strcmp(value, "base64") != 0) 138 context.reportError("Unexpected value of 'encoding'."); 139 } 140 } 141 142 void FlatMessageIO::xmlImportContent( 143 const char* data, 144 uint32 length, 145 ImportContext& context) { 146 m_base64Data.Append(data, length); 147 } 148 149 void FlatMessageIO::xmlImportChild( 150 IPersistent* child, 151 ImportContext& context) { 152 delete child; 153 context.reportError("Unexpected child object."); 154 } 155 156 void FlatMessageIO::xmlImportComplete( 157 ImportContext& context) { 158 159 if(m_ownMessage && m_message) 160 delete m_message; 161 162 // decode the message 163 ssize_t decodedSize = m_base64Data.Length(); 164 char* decodedData = new char[decodedSize]; 165 decodedSize = decode_base64( 166 decodedData, const_cast<char*>(m_base64Data.String()), 167 m_base64Data.Length(), false); 168 169 m_message = new BMessage(); 170 m_ownMessage = true; 171 172 status_t err = m_message->Unflatten(decodedData); 173 if(err < B_OK) { 174 // decode failed; report error & clean up 175 BString error = "Unflatten(): "; 176 error << strerror(err); 177 context.reportError(error.String()); 178 179 delete m_message; 180 m_message = 0; 181 } 182 183 m_base64Data = ""; 184 delete [] decodedData; 185 } 186 187 // END -- FlatMessageIO.cpp -- 188