Fairport
v1.0.38
|
00001 00002 00003 00004 00005 00006 00007 00008 #ifndef FAIRPORT_PST_MESSAGE_H 00009 #define FAIRPORT_PST_MESSAGE_H 00010 00011 #include <functional> 00012 #include <ostream> 00013 #include <boost/iterator/transform_iterator.hpp> 00014 00015 #include "fairport/ndb/database_iface.h" 00016 #include "fairport/ndb/node.h" 00017 00018 #include "fairport/ltp/propbag.h" 00019 #include "fairport/ltp/table.h" 00020 00021 #include "fairport/pst/pstutil.h" 00022 00023 namespace fairport 00024 { 00025 00028 00029 class message; 00030 class contact; 00037 class attachment 00038 { 00039 public: 00040 // property access 00045 std::wstring get_filename() const; 00052 std::vector<byte> get_bytes() const 00053 { return m_bag.read_prop<std::vector<byte> >(0x3701); } 00064 hnid_stream_device open_byte_stream() 00065 { return m_bag.open_prop_stream(0x3701); } 00073 size_t size() const 00074 { return m_bag.read_prop<uint>(0xe20); } 00079 size_t content_size() const 00080 { return m_bag.size(0x3701); } 00087 bool is_message() const 00088 { return m_bag.read_prop<uint>(0x3705) == 5; } 00092 message open_as_message() const; 00093 00094 // lower layer access 00097 property_bag& get_property_bag() 00098 { return m_bag; } 00100 const property_bag& get_property_bag() const 00101 { return m_bag; } 00102 00103 private: 00104 attachment& operator=(const attachment&); // = delete 00105 friend class message; 00106 friend class contact; 00107 friend class attachment_transform; 00108 00109 explicit attachment(const property_bag& attachment) 00110 : m_bag(attachment) { } 00111 00112 property_bag m_bag; 00113 }; 00114 00120 inline std::ostream& operator<<(std::ostream& out, const attachment& attach) 00121 { 00122 std::vector<byte> data = attach.get_bytes(); 00123 out.write(reinterpret_cast<char*>(&data[0]), data.size()); 00124 return out; 00125 } 00126 00131 class attachment_transform : public std::unary_function<const_table_row, attachment> 00132 { 00133 public: 00136 explicit attachment_transform(const node& n) 00137 : m_node(n) { } 00138 00142 attachment operator()(const const_table_row& row) const 00143 { return attachment(property_bag(m_node.lookup(row.get_row_id()))); } 00144 00145 private: 00146 node m_node; 00147 }; 00148 00153 class recipient 00154 { 00155 public: 00156 // property access 00160 std::wstring get_name() const 00161 { return m_row.read_prop<std::wstring>(0x3001); } 00165 recipient_type get_type() const 00166 { return static_cast<recipient_type>(m_row.read_prop<ulong>(0xc15)); } 00170 std::wstring get_address_type() const 00171 { return m_row.read_prop<std::wstring>(0x3002); } 00175 std::wstring get_email_address() const 00176 { return m_row.read_prop<std::wstring>(0x39fe); } 00179 bool has_email_address() const 00180 { return m_row.prop_exists(0x39fe); } 00184 std::wstring get_account_name() const 00185 { return m_row.read_prop<std::wstring>(0x3a00); } 00188 bool has_account_name() const 00189 { return m_row.prop_exists(0x3a00); } 00190 00191 // lower layer access 00194 const_table_row& get_property_row() 00195 { return m_row; } 00197 const const_table_row& get_property_row() const 00198 { return m_row; } 00199 00200 private: 00201 recipient& operator=(const recipient&); // = delete 00202 friend struct recipient_transform; 00203 00204 explicit recipient(const const_table_row& row) 00205 : m_row(row) { } 00206 const_table_row m_row; 00207 }; 00208 00213 struct recipient_transform : public std::unary_function<const_table_row, recipient> 00214 { 00215 recipient operator()(const_table_row row) const 00216 { return recipient(row); } 00217 }; 00218 00229 class message : public detail::itembase 00230 { 00231 public: 00233 typedef boost::transform_iterator<attachment_transform, const_table_row_iter> attachment_iterator; 00235 typedef boost::transform_iterator<recipient_transform, const_table_row_iter> recipient_iterator; 00236 00239 explicit message(const node& n) 00240 : detail::itembase(n) { } 00241 message(const message& other); 00242 00243 // subobject discovery/enumeration 00246 attachment_iterator attachment_begin() const 00247 { return boost::make_transform_iterator(get_attachment_table().begin(), attachment_transform(get_property_bag().get_node())); } 00250 attachment_iterator attachment_end() const 00251 { return boost::make_transform_iterator(get_attachment_table().end(), attachment_transform(get_property_bag().get_node())); } 00254 recipient_iterator recipient_begin() const 00255 { return boost::make_transform_iterator(get_recipient_table().begin(), recipient_transform()); } 00258 recipient_iterator recipient_end() const 00259 { return boost::make_transform_iterator(get_recipient_table().end(), recipient_transform()); } 00260 00261 // property access 00265 std::wstring get_subject() const; 00268 bool has_subject() const 00269 { return get_property_bag().prop_exists(0x37); } 00273 std::wstring get_body() const 00274 { return get_property_bag().read_prop<std::wstring>(0x1000); } 00285 hnid_stream_device open_body_stream() 00286 { return get_property_bag().open_prop_stream(0x1000); } 00289 size_t body_size() const 00290 { return get_property_bag().size(0x1000); } 00293 bool has_body() const 00294 { return get_property_bag().prop_exists(0x1000); } 00298 std::wstring get_html_body() const 00299 { return get_property_bag().read_prop<std::wstring>(0x1013); } 00310 hnid_stream_device open_html_body_stream() 00311 { return get_property_bag().open_prop_stream(0x1013); } 00314 size_t html_body_size() const 00315 { return get_property_bag().size(0x1013); } 00318 bool has_html_body() const 00319 { return get_property_bag().prop_exists(0x1013); } 00320 // \brief Get the total size of this message 00323 size_t size() const 00324 { return get_property_bag().read_prop<slong>(0xe08); } 00327 size_t get_attachment_count() const 00328 { return get_attachment_table().size(); } 00332 boost::posix_time::ptime get_delivery_time() const 00333 { return get_property_bag().read_prop<boost::posix_time::ptime>(0x0e06); } 00337 boost::posix_time::ptime get_last_modification_time() const 00338 { return get_property_bag().read_prop<boost::posix_time::ptime>(0x3008); } 00339 00342 size_t get_recipient_count() const 00343 { return get_recipient_table().size(); } 00344 00345 // lower layer access 00348 table& get_attachment_table() 00349 { return const_cast<table&>(const_cast<const message*>(this)->get_attachment_table()); } 00352 table& get_recipient_table() 00353 { return const_cast<table&>(const_cast<const message*>(this)->get_recipient_table()); } 00355 const table& get_attachment_table() const; 00357 const table& get_recipient_table() const; 00358 00359 private: 00360 mutable std::tr1::shared_ptr<table> m_attachment_table; 00361 mutable std::tr1::shared_ptr<table> m_recipient_table; 00362 }; 00363 00364 typedef detail::item_transform_row<message> message_transform_row; 00365 typedef detail::item_transform_info<message> message_transform_info; 00366 } // end namespace fairport 00367 00368 inline std::wstring fairport::attachment::get_filename() const 00369 { 00370 try 00371 { 00372 return m_bag.read_prop<std::wstring>(0x3707); 00373 } 00374 catch(key_not_found<prop_id>&) 00375 { 00376 return m_bag.read_prop<std::wstring>(0x3704); 00377 } 00378 } 00379 00380 inline fairport::message fairport::attachment::open_as_message() const 00381 { 00382 if(!is_message()) 00383 throw std::bad_cast(); 00384 00385 std::vector<byte> buffer = get_bytes(); 00386 disk::sub_object* psubo = (disk::sub_object*)&buffer[0]; 00387 00388 return message(m_bag.get_node().lookup(psubo->nid)); 00389 } 00390 00391 inline fairport::message::message(const fairport::message& other) 00392 : detail::itembase(other) 00393 { 00394 if(other.m_attachment_table) 00395 m_attachment_table.reset(new table(*other.m_attachment_table)); 00396 if(other.m_recipient_table) 00397 m_recipient_table.reset(new table(*other.m_recipient_table)); 00398 } 00399 00400 inline const fairport::table& fairport::message::get_attachment_table() const 00401 { 00402 if(!m_attachment_table) 00403 { 00404 try 00405 { 00406 m_attachment_table.reset(new table(get_property_bag().get_node().lookup(nid_attachment_table))); 00407 } 00408 catch (const key_not_found<node_id>&) 00409 { 00410 m_attachment_table.reset(new table()); 00411 } 00412 } 00413 00414 return *m_attachment_table; 00415 } 00416 00417 inline const fairport::table& fairport::message::get_recipient_table() const 00418 { 00419 if(!m_recipient_table) 00420 { 00421 try 00422 { 00423 m_recipient_table.reset(new table(get_property_bag().get_node().lookup(nid_recipient_table))); 00424 } 00425 catch (const key_not_found<node_id>&) 00426 { 00427 m_recipient_table.reset(new table()); 00428 } 00429 } 00430 00431 return *m_recipient_table; 00432 } 00433 00434 inline std::wstring fairport::message::get_subject() const 00435 { 00436 std::wstring buffer = get_property_bag().read_prop<std::wstring>(0x37); 00437 00438 if(buffer.size() && buffer[0] == message_subject_prefix_lead_byte) 00439 { 00440 // Skip the second chracter as well 00441 return buffer.substr(2); 00442 } 00443 else 00444 { 00445 return buffer; 00446 } 00447 } 00448 #endif