Mercurial > libpst
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/python-libpst.cpp Mon Apr 20 19:39:26 2009 -0700 @@ -0,0 +1,396 @@ +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include <iostream> +#include <boost/python.hpp> +#include <iostream> + +extern "C" { + #include "libpst.h" + #include "timeconv.h" + #include "libstrfunc.h" + #include "vbuf.h" + #include "lzfu.h" +} + +using namespace std; +using namespace boost::python; + + +/** python version of pst_binary, where python is + responsible for freeing the underlying buffer */ +struct ppst_binary : public pst_binary +{ +}; + +class pst { +public: + pst(const string filename); + virtual ~pst(); + pst_desc_tree* pst_getTopOfFolders(); + ppst_binary pst_attach_to_mem(pst_item_attach *attach); + size_t pst_attach_to_file(pst_item_attach *attach, FILE* fp); + size_t pst_attach_to_file_base64(pst_item_attach *attach, FILE* fp); + pst_desc_tree* pst_getNextDptr(pst_desc_tree* d); + pst_item* pst_parse_item(pst_desc_tree *d_ptr, pst_id2_tree *m_head); + void pst_freeItem(pst_item *item); + pst_index_ll* pst_getID(uint64_t i_id); + int pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type); + size_t pst_ff_getIDblock_dec(uint64_t i_id, char **buf); + size_t pst_ff_getIDblock(uint64_t i_id, char** buf); + string pst_rfc2426_escape(char *str); + string pst_rfc2425_datetime_format(const FILETIME *ft); + string pst_rfc2445_datetime_format(const FILETIME *ft); + string pst_default_charset(pst_item *item); + void pst_convert_utf8_null(pst_item *item, pst_string *str); + void pst_convert_utf8(pst_item *item, pst_string *str); + +private: + bool is_open; + pst_file pf; + pst_item* root; + pst_desc_tree* topf; + +}; + + +pst::pst(const string filename) { + 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 + is_open = (::pst_open(&pf, f) == 0); + root = NULL; + topf = NULL; + if (is_open) { + ::pst_load_index(&pf); + ::pst_load_extended_attributes(&pf); + root = ::pst_parse_item(&pf, pf.d_head, NULL); + topf = ::pst_getTopOfFolders(&pf, root)->child; + } +} + +pst::~pst() { + if (root) pst_freeItem(root); + if (is_open) ::pst_close(&pf); +} + +pst_desc_tree* pst::pst_getTopOfFolders() { + return topf; +} + +ppst_binary pst::pst_attach_to_mem(pst_item_attach *attach) { + ppst_binary rc; + rc.size = rc.size = ::pst_attach_to_mem(&pf, attach, &rc.data); + return rc; +} + +size_t pst::pst_attach_to_file(pst_item_attach *attach, FILE* fp) { + return ::pst_attach_to_file(&pf, attach, fp); +} + +size_t pst::pst_attach_to_file_base64(pst_item_attach *attach, FILE* fp) { + return ::pst_attach_to_file_base64(&pf, attach, fp); +} + +pst_desc_tree* pst::pst_getNextDptr(pst_desc_tree* d) { + return ::pst_getNextDptr(d); +} + +pst_item* pst::pst_parse_item (pst_desc_tree *d_ptr, pst_id2_tree *m_head) { + return ::pst_parse_item(&pf, d_ptr, m_head); +} + +void pst::pst_freeItem(pst_item *item) { + return ::pst_freeItem(item); +} + +pst_index_ll* pst::pst_getID(uint64_t i_id) { + return ::pst_getID(&pf, i_id); +} + +int pst::pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type) { + return ::pst_decrypt(i_id, buf, size, type); +} + +size_t pst::pst_ff_getIDblock_dec(uint64_t i_id, char **buf) { + return ::pst_ff_getIDblock_dec(&pf, i_id, buf); +} + +size_t pst::pst_ff_getIDblock(uint64_t i_id, char** buf) { + return ::pst_ff_getIDblock(&pf, i_id, buf); +} + +string pst::pst_rfc2426_escape(char *str) { + return ::pst_rfc2426_escape(str); +} + +string pst::pst_rfc2425_datetime_format(const FILETIME *ft) { + 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 +} + +string pst::pst_rfc2445_datetime_format(const FILETIME *ft) { + 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 +} + +string pst::pst_default_charset(pst_item *item) { + return ::pst_default_charset(item); +} + +void pst::pst_convert_utf8_null(pst_item *item, pst_string *str) { + ::pst_convert_utf8_null(item, str); +} + +void pst::pst_convert_utf8(pst_item *item, pst_string *str) { + ::pst_convert_utf8(item, str); +} + +struct make_python_string { + /* we make no distinction between empty and null strings */ + static PyObject* convert(char* const &s) { + string ss; + if (s) ss = string(s); + return boost::python::incref(boost::python::object(ss).ptr()); + } +}; + +struct make_python_pst_binary { + static PyObject* convert(pst_binary const &s) { + if (s.data) { + string ss; + ss = string(s.data, s.size); + return boost::python::incref(boost::python::object(ss).ptr()); + } + return NULL; + } +}; + +struct make_python_ppst_binary { + static PyObject* convert(ppst_binary const &s) { + if (s.data) { + string ss; + ss = string(s.data, s.size); + free(s.data); + return boost::python::incref(boost::python::object(ss).ptr()); + } + return NULL; + } +}; + +struct make_python_pst_item_email { + static PyObject* convert(pst_item_email* const &s) { + if (s) return to_python_indirect<pst_item_email*, detail::make_reference_holder>()(s); + return NULL; + } +}; + +struct make_python_pst_item_attach { + static PyObject* convert(pst_item_attach* const &s) { + if (s) return to_python_indirect<pst_item_attach*, detail::make_reference_holder>()(s); + return NULL; + } +}; + +struct make_python_pst_desc_tree { + static PyObject* convert(pst_desc_tree* const &s) { + if (s) return to_python_indirect<pst_desc_tree*, detail::make_reference_holder>()(s); + return NULL; + } +}; + +struct make_python_pst_index_ll { + static PyObject* convert(pst_index_ll* const &s) { + if (s) return to_python_indirect<pst_index_ll*, detail::make_reference_holder>()(s); + return NULL; + } +}; + +BOOST_PYTHON_MODULE(_libpst) +{ + to_python_converter<pst_binary, make_python_pst_binary>(); + to_python_converter<ppst_binary, make_python_ppst_binary>(); + to_python_converter<char*, make_python_string>(); + to_python_converter<pst_item_email*, make_python_pst_item_email>(); + to_python_converter<pst_item_attach*, make_python_pst_item_attach>(); + to_python_converter<pst_desc_tree*, make_python_pst_desc_tree>(); + to_python_converter<pst_index_ll*, make_python_pst_index_ll>(); + + class_<FILETIME>("FILETIME") + .def_readonly("dwLowDateTime", &FILETIME::dwLowDateTime) + .def_readonly("dwHighDateTime", &FILETIME::dwHighDateTime) + ; + + class_<pst_entryid>("pst_entryid") + .def_readonly("u1", &pst_entryid::u1) + .def_readonly("entryid", &pst_entryid::entryid) + .def_readonly("id", &pst_entryid::id) + ; + + class_<pst_index_ll>("pst_index_ll") + .def_readonly("i_id", &pst_index_ll::i_id) + .def_readonly("offset", &pst_index_ll::offset) + .def_readonly("size", &pst_index_ll::size) + .def_readonly("u1", &pst_index_ll::u1) + .add_property("next", make_getter(&pst_index_ll::next, return_value_policy<reference_existing_object>())) + ; + + class_<pst_id2_tree>("pst_id2_tree") + .def_readonly("id2", &pst_id2_tree::id2) + .add_property("id", make_getter(&pst_id2_tree::id, return_value_policy<reference_existing_object>())) + .add_property("child", make_getter(&pst_id2_tree::child, return_value_policy<reference_existing_object>())) + .add_property("next", make_getter(&pst_id2_tree::next, return_value_policy<reference_existing_object>())) + ; + + class_<pst_desc_tree>("pst_desc_tree") + .def_readonly("d_id", &pst_desc_tree::d_id) + .def_readonly("parent_d_id", &pst_desc_tree::parent_d_id) + .add_property("desc", make_getter(&pst_desc_tree::desc, return_value_policy<reference_existing_object>())) + .add_property("assoc_tree", make_getter(&pst_desc_tree::assoc_tree, return_value_policy<reference_existing_object>())) + .def_readonly("no_child", &pst_desc_tree::no_child) + .add_property("prev", make_getter(&pst_desc_tree::prev, return_value_policy<reference_existing_object>())) + .add_property("next", make_getter(&pst_desc_tree::next, return_value_policy<reference_existing_object>())) + .add_property("parent", make_getter(&pst_desc_tree::parent, return_value_policy<reference_existing_object>())) + .add_property("child", make_getter(&pst_desc_tree::child, return_value_policy<reference_existing_object>())) + .add_property("child_tail", make_getter(&pst_desc_tree::child_tail, return_value_policy<reference_existing_object>())) + ; + + class_<pst_string>("pst_string") + .def_readonly("is_utf8", &pst_string::is_utf8) + .def_readonly("str", &pst_string::str) + ; + + class_<pst_item_email>("pst_item_email") + .add_property("arrival_date", make_getter(&pst_item_email::arrival_date, return_value_policy<reference_existing_object>())) + .def_readonly("autoforward", &pst_item_email::autoforward) + .def_readonly("cc_address", &pst_item_email::cc_address) + .def_readonly("bcc_address", &pst_item_email::bcc_address) + .def_readonly("conversation_index", &pst_item_email::conversation_index) + .def_readonly("conversion_prohibited", &pst_item_email::conversion_prohibited) + .def_readonly("delete_after_submit", &pst_item_email::delete_after_submit) + .def_readonly("delivery_report", &pst_item_email::delivery_report) + .def_readonly("encrypted_body", &pst_item_email::encrypted_body) + .def_readonly("encrypted_htmlbody", &pst_item_email::encrypted_htmlbody) + .def_readonly("header", &pst_item_email::header) + .def_readonly("htmlbody", &pst_item_email::htmlbody) + .def_readonly("importance", &pst_item_email::importance) + .def_readonly("in_reply_to", &pst_item_email::in_reply_to) + .def_readonly("message_cc_me", &pst_item_email::message_cc_me) + .def_readonly("message_recip_me", &pst_item_email::message_recip_me) + .def_readonly("message_to_me", &pst_item_email::message_to_me) + .def_readonly("messageid", &pst_item_email::messageid) + .def_readonly("original_sensitivity", &pst_item_email::original_sensitivity) + .def_readonly("original_bcc", &pst_item_email::original_bcc) + .def_readonly("original_cc", &pst_item_email::original_cc) + .def_readonly("original_to", &pst_item_email::original_to) + ; + + class_<pst_item_folder>("pst_item_folder") + .def_readonly("item_count", &pst_item_folder::item_count) + ; + + class_<pst_item_message_store>("pst_item_message_store") + .add_property("top_of_personal_folder", make_getter(&pst_item_message_store::top_of_personal_folder, return_value_policy<reference_existing_object>())) + ; + + class_<pst_item_contact>("pst_item_contact") + .def_readonly("account_name", &pst_item_contact::account_name) + ; + + class_<pst_item_attach>("pst_item_attach") + .def_readonly("filename1", &pst_item_attach::filename1) + .def_readonly("filename2", &pst_item_attach::filename2) + .def_readonly("mimetype", &pst_item_attach::mimetype) + .def_readonly("data", &pst_item_attach::data) + .def_readonly("id2_val", &pst_item_attach::id2_val) + .def_readonly("i_id", &pst_item_attach::i_id) + .add_property("id2_head", make_getter(&pst_item_attach::id2_head, return_value_policy<reference_existing_object>())) + .def_readonly("method", &pst_item_attach::method) + .def_readonly("position", &pst_item_attach::position) + .def_readonly("sequence", &pst_item_attach::sequence) + .add_property("next", make_getter(&pst_item_attach::next, return_value_policy<reference_existing_object>())) + ; + + class_<pst_item_extra_field>("pst_item_extra_field") + .def_readonly("field_name", &pst_item_extra_field::field_name) + ; + + class_<pst_item_journal>("pst_item_journal") + .def_readonly("description", &pst_item_journal::description) + ; + + class_<pst_item_appointment>("pst_item_appointment") + .add_property("end", make_getter(&pst_item_appointment::end, return_value_policy<reference_existing_object>())) + .def_readonly("label", &pst_item_appointment::label) + ; + + class_<pst_item>("pst_item") + .add_property("email", make_getter(&pst_item::email, return_value_policy<reference_existing_object>())) + .add_property("folder", make_getter(&pst_item::folder, return_value_policy<reference_existing_object>())) + .add_property("contact", make_getter(&pst_item::contact, return_value_policy<reference_existing_object>())) + .add_property("attach", make_getter(&pst_item::attach, return_value_policy<reference_existing_object>())) + .add_property("message_store", make_getter(&pst_item::message_store, return_value_policy<reference_existing_object>())) + .add_property("extra_fields", make_getter(&pst_item::extra_fields, return_value_policy<reference_existing_object>())) + .add_property("journal", make_getter(&pst_item::journal, return_value_policy<reference_existing_object>())) + .add_property("appointment", make_getter(&pst_item::appointment, return_value_policy<reference_existing_object>())) + .def_readonly("type", &pst_item::type) + .def_readonly("ascii_type", &pst_item::ascii_type) + .def_readonly("flags", &pst_item::flags) + .def_readonly("file_as", &pst_item::file_as) + .def_readonly("comment", &pst_item::comment) + .def_readonly("body_charset", &pst_item::body_charset) + .def_readonly("body", &pst_item::body) + .def_readonly("subject", &pst_item::subject) + .def_readonly("internet_cpid", &pst_item::internet_cpid) + .def_readonly("message_codepage", &pst_item::message_codepage) + .def_readonly("message_size", &pst_item::message_size) + .def_readonly("outlook_version", &pst_item::outlook_version) + .def_readonly("record_key", &pst_item::record_key) + .def_readonly("predecessor_change", &pst_item::predecessor_change) + .def_readonly("response_requested", &pst_item::response_requested) + .add_property("create_date", make_getter(&pst_item::create_date, return_value_policy<reference_existing_object>())) + .add_property("modify_date", make_getter(&pst_item::modify_date, return_value_policy<reference_existing_object>())) + .def_readonly("private_member", &pst_item::private_member) + ; + + class_<pst_x_attrib_ll>("pst_x_attrib_ll") + .def_readonly("mytype", &pst_x_attrib_ll::mytype) + .def_readonly("map", &pst_x_attrib_ll::map) + .def_readonly("data", &pst_x_attrib_ll::data) + .def_readonly("next", &pst_x_attrib_ll::next) + ; + + class_<pst_file>("pst_file") + .add_property("i_head", make_getter(&pst_file::i_head, return_value_policy<reference_existing_object>())) + .add_property("i_tail", make_getter(&pst_file::i_tail, return_value_policy<reference_existing_object>())) + .add_property("d_head", make_getter(&pst_file::d_head, return_value_policy<reference_existing_object>())) + .add_property("d_tail", make_getter(&pst_file::d_tail, return_value_policy<reference_existing_object>())) + .def_readonly("do_read64", &pst_file::do_read64) + .def_readonly("index1", &pst_file::index1) + .def_readonly("index1_back", &pst_file::index1_back) + .def_readonly("index2", &pst_file::index2) + .def_readonly("index2_back", &pst_file::index2_back) + .def_readonly("size", &pst_file::size) + .def_readonly("encryption", &pst_file::encryption) + .def_readonly("ind_type", &pst_file::ind_type) + ; + + class_<pst>("pst", init<string>()) + .def("pst_getTopOfFolders", &pst::pst_getTopOfFolders, return_value_policy<reference_existing_object>()) + .def("pst_attach_to_mem", &pst::pst_attach_to_mem) + .def("pst_attach_to_file", &pst::pst_attach_to_file) + .def("pst_attach_to_file_base64", &pst::pst_attach_to_file_base64) + .def("pst_getNextDptr", &pst::pst_getNextDptr, return_value_policy<reference_existing_object>()) + .def("pst_parse_item", &pst::pst_parse_item, return_value_policy<reference_existing_object>()) + .def("pst_freeItem", &pst::pst_freeItem) + .def("pst_getID", &pst::pst_getID, return_value_policy<reference_existing_object>()) + .def("pst_decrypt", &pst::pst_decrypt) + .def("pst_ff_getIDblock_dec", &pst::pst_ff_getIDblock_dec) + .def("pst_ff_getIDblock", &pst::pst_ff_getIDblock) + .def("pst_rfc2426_escape", &pst::pst_rfc2426_escape) + .def("pst_rfc2425_datetime_format", &pst::pst_rfc2425_datetime_format) + .def("pst_rfc2445_datetime_format", &pst::pst_rfc2445_datetime_format) + .def("pst_default_charset", &pst::pst_default_charset) + .def("pst_convert_utf8_null", &pst::pst_convert_utf8_null) + .def("pst_convert_utf8", &pst::pst_convert_utf8) + ; +} + +