Mercurial > libpst
comparison python/python-libpst.cpp @ 195:320cfcba8058
add python module interface to the shared library for easy scripting.
the shared library must never write to stdout or stderr.
fix pst_attach_to_mem so the caller does not need to initialize the buffer pointer.
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 20 Apr 2009 19:39:26 -0700 |
parents | |
children | ffd1503a7530 |
comparison
equal
deleted
inserted
replaced
194:885b47107036 | 195:320cfcba8058 |
---|---|
1 #ifdef HAVE_CONFIG_H | |
2 #include "config.h" | |
3 #endif | |
4 | |
5 #include <iostream> | |
6 #include <boost/python.hpp> | |
7 #include <iostream> | |
8 | |
9 extern "C" { | |
10 #include "libpst.h" | |
11 #include "timeconv.h" | |
12 #include "libstrfunc.h" | |
13 #include "vbuf.h" | |
14 #include "lzfu.h" | |
15 } | |
16 | |
17 using namespace std; | |
18 using namespace boost::python; | |
19 | |
20 | |
21 /** python version of pst_binary, where python is | |
22 responsible for freeing the underlying buffer */ | |
23 struct ppst_binary : public pst_binary | |
24 { | |
25 }; | |
26 | |
27 class pst { | |
28 public: | |
29 pst(const string filename); | |
30 virtual ~pst(); | |
31 pst_desc_tree* pst_getTopOfFolders(); | |
32 ppst_binary pst_attach_to_mem(pst_item_attach *attach); | |
33 size_t pst_attach_to_file(pst_item_attach *attach, FILE* fp); | |
34 size_t pst_attach_to_file_base64(pst_item_attach *attach, FILE* fp); | |
35 pst_desc_tree* pst_getNextDptr(pst_desc_tree* d); | |
36 pst_item* pst_parse_item(pst_desc_tree *d_ptr, pst_id2_tree *m_head); | |
37 void pst_freeItem(pst_item *item); | |
38 pst_index_ll* pst_getID(uint64_t i_id); | |
39 int pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type); | |
40 size_t pst_ff_getIDblock_dec(uint64_t i_id, char **buf); | |
41 size_t pst_ff_getIDblock(uint64_t i_id, char** buf); | |
42 string pst_rfc2426_escape(char *str); | |
43 string pst_rfc2425_datetime_format(const FILETIME *ft); | |
44 string pst_rfc2445_datetime_format(const FILETIME *ft); | |
45 string pst_default_charset(pst_item *item); | |
46 void pst_convert_utf8_null(pst_item *item, pst_string *str); | |
47 void pst_convert_utf8(pst_item *item, pst_string *str); | |
48 | |
49 private: | |
50 bool is_open; | |
51 pst_file pf; | |
52 pst_item* root; | |
53 pst_desc_tree* topf; | |
54 | |
55 }; | |
56 | |
57 | |
58 pst::pst(const string filename) { | |
59 char *f = (char *)filename.c_str(); // ok, since pst_open does not actually modify this buffer, and newer versions will change the signature to const anyway | |
60 is_open = (::pst_open(&pf, f) == 0); | |
61 root = NULL; | |
62 topf = NULL; | |
63 if (is_open) { | |
64 ::pst_load_index(&pf); | |
65 ::pst_load_extended_attributes(&pf); | |
66 root = ::pst_parse_item(&pf, pf.d_head, NULL); | |
67 topf = ::pst_getTopOfFolders(&pf, root)->child; | |
68 } | |
69 } | |
70 | |
71 pst::~pst() { | |
72 if (root) pst_freeItem(root); | |
73 if (is_open) ::pst_close(&pf); | |
74 } | |
75 | |
76 pst_desc_tree* pst::pst_getTopOfFolders() { | |
77 return topf; | |
78 } | |
79 | |
80 ppst_binary pst::pst_attach_to_mem(pst_item_attach *attach) { | |
81 ppst_binary rc; | |
82 rc.size = rc.size = ::pst_attach_to_mem(&pf, attach, &rc.data); | |
83 return rc; | |
84 } | |
85 | |
86 size_t pst::pst_attach_to_file(pst_item_attach *attach, FILE* fp) { | |
87 return ::pst_attach_to_file(&pf, attach, fp); | |
88 } | |
89 | |
90 size_t pst::pst_attach_to_file_base64(pst_item_attach *attach, FILE* fp) { | |
91 return ::pst_attach_to_file_base64(&pf, attach, fp); | |
92 } | |
93 | |
94 pst_desc_tree* pst::pst_getNextDptr(pst_desc_tree* d) { | |
95 return ::pst_getNextDptr(d); | |
96 } | |
97 | |
98 pst_item* pst::pst_parse_item (pst_desc_tree *d_ptr, pst_id2_tree *m_head) { | |
99 return ::pst_parse_item(&pf, d_ptr, m_head); | |
100 } | |
101 | |
102 void pst::pst_freeItem(pst_item *item) { | |
103 return ::pst_freeItem(item); | |
104 } | |
105 | |
106 pst_index_ll* pst::pst_getID(uint64_t i_id) { | |
107 return ::pst_getID(&pf, i_id); | |
108 } | |
109 | |
110 int pst::pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type) { | |
111 return ::pst_decrypt(i_id, buf, size, type); | |
112 } | |
113 | |
114 size_t pst::pst_ff_getIDblock_dec(uint64_t i_id, char **buf) { | |
115 return ::pst_ff_getIDblock_dec(&pf, i_id, buf); | |
116 } | |
117 | |
118 size_t pst::pst_ff_getIDblock(uint64_t i_id, char** buf) { | |
119 return ::pst_ff_getIDblock(&pf, i_id, buf); | |
120 } | |
121 | |
122 string pst::pst_rfc2426_escape(char *str) { | |
123 return ::pst_rfc2426_escape(str); | |
124 } | |
125 | |
126 string pst::pst_rfc2425_datetime_format(const FILETIME *ft) { | |
127 return ::pst_rfc2425_datetime_format((FILETIME *)ft); // cast away const is ok, since libpst did not modify it anyway, and the signature will change in more recent versions | |
128 } | |
129 | |
130 string pst::pst_rfc2445_datetime_format(const FILETIME *ft) { | |
131 return ::pst_rfc2445_datetime_format((FILETIME *)ft); // cast away const is ok, since libpst did not modify it anyway, and the signature will change in more recent versions | |
132 } | |
133 | |
134 string pst::pst_default_charset(pst_item *item) { | |
135 return ::pst_default_charset(item); | |
136 } | |
137 | |
138 void pst::pst_convert_utf8_null(pst_item *item, pst_string *str) { | |
139 ::pst_convert_utf8_null(item, str); | |
140 } | |
141 | |
142 void pst::pst_convert_utf8(pst_item *item, pst_string *str) { | |
143 ::pst_convert_utf8(item, str); | |
144 } | |
145 | |
146 struct make_python_string { | |
147 /* we make no distinction between empty and null strings */ | |
148 static PyObject* convert(char* const &s) { | |
149 string ss; | |
150 if (s) ss = string(s); | |
151 return boost::python::incref(boost::python::object(ss).ptr()); | |
152 } | |
153 }; | |
154 | |
155 struct make_python_pst_binary { | |
156 static PyObject* convert(pst_binary const &s) { | |
157 if (s.data) { | |
158 string ss; | |
159 ss = string(s.data, s.size); | |
160 return boost::python::incref(boost::python::object(ss).ptr()); | |
161 } | |
162 return NULL; | |
163 } | |
164 }; | |
165 | |
166 struct make_python_ppst_binary { | |
167 static PyObject* convert(ppst_binary const &s) { | |
168 if (s.data) { | |
169 string ss; | |
170 ss = string(s.data, s.size); | |
171 free(s.data); | |
172 return boost::python::incref(boost::python::object(ss).ptr()); | |
173 } | |
174 return NULL; | |
175 } | |
176 }; | |
177 | |
178 struct make_python_pst_item_email { | |
179 static PyObject* convert(pst_item_email* const &s) { | |
180 if (s) return to_python_indirect<pst_item_email*, detail::make_reference_holder>()(s); | |
181 return NULL; | |
182 } | |
183 }; | |
184 | |
185 struct make_python_pst_item_attach { | |
186 static PyObject* convert(pst_item_attach* const &s) { | |
187 if (s) return to_python_indirect<pst_item_attach*, detail::make_reference_holder>()(s); | |
188 return NULL; | |
189 } | |
190 }; | |
191 | |
192 struct make_python_pst_desc_tree { | |
193 static PyObject* convert(pst_desc_tree* const &s) { | |
194 if (s) return to_python_indirect<pst_desc_tree*, detail::make_reference_holder>()(s); | |
195 return NULL; | |
196 } | |
197 }; | |
198 | |
199 struct make_python_pst_index_ll { | |
200 static PyObject* convert(pst_index_ll* const &s) { | |
201 if (s) return to_python_indirect<pst_index_ll*, detail::make_reference_holder>()(s); | |
202 return NULL; | |
203 } | |
204 }; | |
205 | |
206 BOOST_PYTHON_MODULE(_libpst) | |
207 { | |
208 to_python_converter<pst_binary, make_python_pst_binary>(); | |
209 to_python_converter<ppst_binary, make_python_ppst_binary>(); | |
210 to_python_converter<char*, make_python_string>(); | |
211 to_python_converter<pst_item_email*, make_python_pst_item_email>(); | |
212 to_python_converter<pst_item_attach*, make_python_pst_item_attach>(); | |
213 to_python_converter<pst_desc_tree*, make_python_pst_desc_tree>(); | |
214 to_python_converter<pst_index_ll*, make_python_pst_index_ll>(); | |
215 | |
216 class_<FILETIME>("FILETIME") | |
217 .def_readonly("dwLowDateTime", &FILETIME::dwLowDateTime) | |
218 .def_readonly("dwHighDateTime", &FILETIME::dwHighDateTime) | |
219 ; | |
220 | |
221 class_<pst_entryid>("pst_entryid") | |
222 .def_readonly("u1", &pst_entryid::u1) | |
223 .def_readonly("entryid", &pst_entryid::entryid) | |
224 .def_readonly("id", &pst_entryid::id) | |
225 ; | |
226 | |
227 class_<pst_index_ll>("pst_index_ll") | |
228 .def_readonly("i_id", &pst_index_ll::i_id) | |
229 .def_readonly("offset", &pst_index_ll::offset) | |
230 .def_readonly("size", &pst_index_ll::size) | |
231 .def_readonly("u1", &pst_index_ll::u1) | |
232 .add_property("next", make_getter(&pst_index_ll::next, return_value_policy<reference_existing_object>())) | |
233 ; | |
234 | |
235 class_<pst_id2_tree>("pst_id2_tree") | |
236 .def_readonly("id2", &pst_id2_tree::id2) | |
237 .add_property("id", make_getter(&pst_id2_tree::id, return_value_policy<reference_existing_object>())) | |
238 .add_property("child", make_getter(&pst_id2_tree::child, return_value_policy<reference_existing_object>())) | |
239 .add_property("next", make_getter(&pst_id2_tree::next, return_value_policy<reference_existing_object>())) | |
240 ; | |
241 | |
242 class_<pst_desc_tree>("pst_desc_tree") | |
243 .def_readonly("d_id", &pst_desc_tree::d_id) | |
244 .def_readonly("parent_d_id", &pst_desc_tree::parent_d_id) | |
245 .add_property("desc", make_getter(&pst_desc_tree::desc, return_value_policy<reference_existing_object>())) | |
246 .add_property("assoc_tree", make_getter(&pst_desc_tree::assoc_tree, return_value_policy<reference_existing_object>())) | |
247 .def_readonly("no_child", &pst_desc_tree::no_child) | |
248 .add_property("prev", make_getter(&pst_desc_tree::prev, return_value_policy<reference_existing_object>())) | |
249 .add_property("next", make_getter(&pst_desc_tree::next, return_value_policy<reference_existing_object>())) | |
250 .add_property("parent", make_getter(&pst_desc_tree::parent, return_value_policy<reference_existing_object>())) | |
251 .add_property("child", make_getter(&pst_desc_tree::child, return_value_policy<reference_existing_object>())) | |
252 .add_property("child_tail", make_getter(&pst_desc_tree::child_tail, return_value_policy<reference_existing_object>())) | |
253 ; | |
254 | |
255 class_<pst_string>("pst_string") | |
256 .def_readonly("is_utf8", &pst_string::is_utf8) | |
257 .def_readonly("str", &pst_string::str) | |
258 ; | |
259 | |
260 class_<pst_item_email>("pst_item_email") | |
261 .add_property("arrival_date", make_getter(&pst_item_email::arrival_date, return_value_policy<reference_existing_object>())) | |
262 .def_readonly("autoforward", &pst_item_email::autoforward) | |
263 .def_readonly("cc_address", &pst_item_email::cc_address) | |
264 .def_readonly("bcc_address", &pst_item_email::bcc_address) | |
265 .def_readonly("conversation_index", &pst_item_email::conversation_index) | |
266 .def_readonly("conversion_prohibited", &pst_item_email::conversion_prohibited) | |
267 .def_readonly("delete_after_submit", &pst_item_email::delete_after_submit) | |
268 .def_readonly("delivery_report", &pst_item_email::delivery_report) | |
269 .def_readonly("encrypted_body", &pst_item_email::encrypted_body) | |
270 .def_readonly("encrypted_htmlbody", &pst_item_email::encrypted_htmlbody) | |
271 .def_readonly("header", &pst_item_email::header) | |
272 .def_readonly("htmlbody", &pst_item_email::htmlbody) | |
273 .def_readonly("importance", &pst_item_email::importance) | |
274 .def_readonly("in_reply_to", &pst_item_email::in_reply_to) | |
275 .def_readonly("message_cc_me", &pst_item_email::message_cc_me) | |
276 .def_readonly("message_recip_me", &pst_item_email::message_recip_me) | |
277 .def_readonly("message_to_me", &pst_item_email::message_to_me) | |
278 .def_readonly("messageid", &pst_item_email::messageid) | |
279 .def_readonly("original_sensitivity", &pst_item_email::original_sensitivity) | |
280 .def_readonly("original_bcc", &pst_item_email::original_bcc) | |
281 .def_readonly("original_cc", &pst_item_email::original_cc) | |
282 .def_readonly("original_to", &pst_item_email::original_to) | |
283 ; | |
284 | |
285 class_<pst_item_folder>("pst_item_folder") | |
286 .def_readonly("item_count", &pst_item_folder::item_count) | |
287 ; | |
288 | |
289 class_<pst_item_message_store>("pst_item_message_store") | |
290 .add_property("top_of_personal_folder", make_getter(&pst_item_message_store::top_of_personal_folder, return_value_policy<reference_existing_object>())) | |
291 ; | |
292 | |
293 class_<pst_item_contact>("pst_item_contact") | |
294 .def_readonly("account_name", &pst_item_contact::account_name) | |
295 ; | |
296 | |
297 class_<pst_item_attach>("pst_item_attach") | |
298 .def_readonly("filename1", &pst_item_attach::filename1) | |
299 .def_readonly("filename2", &pst_item_attach::filename2) | |
300 .def_readonly("mimetype", &pst_item_attach::mimetype) | |
301 .def_readonly("data", &pst_item_attach::data) | |
302 .def_readonly("id2_val", &pst_item_attach::id2_val) | |
303 .def_readonly("i_id", &pst_item_attach::i_id) | |
304 .add_property("id2_head", make_getter(&pst_item_attach::id2_head, return_value_policy<reference_existing_object>())) | |
305 .def_readonly("method", &pst_item_attach::method) | |
306 .def_readonly("position", &pst_item_attach::position) | |
307 .def_readonly("sequence", &pst_item_attach::sequence) | |
308 .add_property("next", make_getter(&pst_item_attach::next, return_value_policy<reference_existing_object>())) | |
309 ; | |
310 | |
311 class_<pst_item_extra_field>("pst_item_extra_field") | |
312 .def_readonly("field_name", &pst_item_extra_field::field_name) | |
313 ; | |
314 | |
315 class_<pst_item_journal>("pst_item_journal") | |
316 .def_readonly("description", &pst_item_journal::description) | |
317 ; | |
318 | |
319 class_<pst_item_appointment>("pst_item_appointment") | |
320 .add_property("end", make_getter(&pst_item_appointment::end, return_value_policy<reference_existing_object>())) | |
321 .def_readonly("label", &pst_item_appointment::label) | |
322 ; | |
323 | |
324 class_<pst_item>("pst_item") | |
325 .add_property("email", make_getter(&pst_item::email, return_value_policy<reference_existing_object>())) | |
326 .add_property("folder", make_getter(&pst_item::folder, return_value_policy<reference_existing_object>())) | |
327 .add_property("contact", make_getter(&pst_item::contact, return_value_policy<reference_existing_object>())) | |
328 .add_property("attach", make_getter(&pst_item::attach, return_value_policy<reference_existing_object>())) | |
329 .add_property("message_store", make_getter(&pst_item::message_store, return_value_policy<reference_existing_object>())) | |
330 .add_property("extra_fields", make_getter(&pst_item::extra_fields, return_value_policy<reference_existing_object>())) | |
331 .add_property("journal", make_getter(&pst_item::journal, return_value_policy<reference_existing_object>())) | |
332 .add_property("appointment", make_getter(&pst_item::appointment, return_value_policy<reference_existing_object>())) | |
333 .def_readonly("type", &pst_item::type) | |
334 .def_readonly("ascii_type", &pst_item::ascii_type) | |
335 .def_readonly("flags", &pst_item::flags) | |
336 .def_readonly("file_as", &pst_item::file_as) | |
337 .def_readonly("comment", &pst_item::comment) | |
338 .def_readonly("body_charset", &pst_item::body_charset) | |
339 .def_readonly("body", &pst_item::body) | |
340 .def_readonly("subject", &pst_item::subject) | |
341 .def_readonly("internet_cpid", &pst_item::internet_cpid) | |
342 .def_readonly("message_codepage", &pst_item::message_codepage) | |
343 .def_readonly("message_size", &pst_item::message_size) | |
344 .def_readonly("outlook_version", &pst_item::outlook_version) | |
345 .def_readonly("record_key", &pst_item::record_key) | |
346 .def_readonly("predecessor_change", &pst_item::predecessor_change) | |
347 .def_readonly("response_requested", &pst_item::response_requested) | |
348 .add_property("create_date", make_getter(&pst_item::create_date, return_value_policy<reference_existing_object>())) | |
349 .add_property("modify_date", make_getter(&pst_item::modify_date, return_value_policy<reference_existing_object>())) | |
350 .def_readonly("private_member", &pst_item::private_member) | |
351 ; | |
352 | |
353 class_<pst_x_attrib_ll>("pst_x_attrib_ll") | |
354 .def_readonly("mytype", &pst_x_attrib_ll::mytype) | |
355 .def_readonly("map", &pst_x_attrib_ll::map) | |
356 .def_readonly("data", &pst_x_attrib_ll::data) | |
357 .def_readonly("next", &pst_x_attrib_ll::next) | |
358 ; | |
359 | |
360 class_<pst_file>("pst_file") | |
361 .add_property("i_head", make_getter(&pst_file::i_head, return_value_policy<reference_existing_object>())) | |
362 .add_property("i_tail", make_getter(&pst_file::i_tail, return_value_policy<reference_existing_object>())) | |
363 .add_property("d_head", make_getter(&pst_file::d_head, return_value_policy<reference_existing_object>())) | |
364 .add_property("d_tail", make_getter(&pst_file::d_tail, return_value_policy<reference_existing_object>())) | |
365 .def_readonly("do_read64", &pst_file::do_read64) | |
366 .def_readonly("index1", &pst_file::index1) | |
367 .def_readonly("index1_back", &pst_file::index1_back) | |
368 .def_readonly("index2", &pst_file::index2) | |
369 .def_readonly("index2_back", &pst_file::index2_back) | |
370 .def_readonly("size", &pst_file::size) | |
371 .def_readonly("encryption", &pst_file::encryption) | |
372 .def_readonly("ind_type", &pst_file::ind_type) | |
373 ; | |
374 | |
375 class_<pst>("pst", init<string>()) | |
376 .def("pst_getTopOfFolders", &pst::pst_getTopOfFolders, return_value_policy<reference_existing_object>()) | |
377 .def("pst_attach_to_mem", &pst::pst_attach_to_mem) | |
378 .def("pst_attach_to_file", &pst::pst_attach_to_file) | |
379 .def("pst_attach_to_file_base64", &pst::pst_attach_to_file_base64) | |
380 .def("pst_getNextDptr", &pst::pst_getNextDptr, return_value_policy<reference_existing_object>()) | |
381 .def("pst_parse_item", &pst::pst_parse_item, return_value_policy<reference_existing_object>()) | |
382 .def("pst_freeItem", &pst::pst_freeItem) | |
383 .def("pst_getID", &pst::pst_getID, return_value_policy<reference_existing_object>()) | |
384 .def("pst_decrypt", &pst::pst_decrypt) | |
385 .def("pst_ff_getIDblock_dec", &pst::pst_ff_getIDblock_dec) | |
386 .def("pst_ff_getIDblock", &pst::pst_ff_getIDblock) | |
387 .def("pst_rfc2426_escape", &pst::pst_rfc2426_escape) | |
388 .def("pst_rfc2425_datetime_format", &pst::pst_rfc2425_datetime_format) | |
389 .def("pst_rfc2445_datetime_format", &pst::pst_rfc2445_datetime_format) | |
390 .def("pst_default_charset", &pst::pst_default_charset) | |
391 .def("pst_convert_utf8_null", &pst::pst_convert_utf8_null) | |
392 .def("pst_convert_utf8", &pst::pst_convert_utf8) | |
393 ; | |
394 } | |
395 | |
396 |