xref: /haiku/src/apps/cortex/Persistence/Wrappers/FlatMessageIO.cpp (revision a0795c6fe30e25338049a952326c61deb7a343b6)
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