PST File Format SDK v0.4
Loading...
Searching...
No Matches
message.h
Go to the documentation of this file.
1
7
8#ifndef PSTSDK_PST_MESSAGE_H
9#define PSTSDK_PST_MESSAGE_H
10
11#include <functional>
12#include <ostream>
13#include <boost/iterator/transform_iterator.hpp>
14
16#include "pstsdk/ndb/node.h"
17
18#include "pstsdk/ltp/propbag.h"
19#include "pstsdk/ltp/table.h"
20#include "pstsdk/mapitags.h"
22
23namespace pstsdk
24{
25
28
29class message;
37{
38public:
39 // property access
42 std::wstring get_filename() const;
48 std::vector<byte> get_bytes() const
49 { return m_bag.read_prop<std::vector<byte> >(PR_ATTACH_DATA_OBJ); }
67 size_t size() const
68 { return m_bag.read_prop<uint>(PR_ATTACH_SIZE); }
73 size_t content_size() const
74 { return m_bag.size(PR_ATTACH_DATA_OBJ); }
80 bool is_message() const
81 { return m_bag.read_prop<uint>(PR_ATTACH_METHOD) == 5; }
86
87 // lower layer access
91 { return m_bag; }
94 { return m_bag; }
95
96private:
97 attachment& operator=(const attachment&); // = delete
98 friend class message;
100
101#ifndef BOOST_NO_RVALUE_REFERENCES
103 : m_bag(std::move(attachment)) { }
104#else
105 explicit attachment(const property_bag& attachment)
106 : m_bag(attachment) { }
107#endif
108 property_bag m_bag;
109};
110
116inline std::ostream& operator<<(std::ostream& out, const attachment& attach)
117{
118 std::vector<byte> data = attach.get_bytes();
119 out.write(reinterpret_cast<char*>(&data[0]), data.size());
120 return out;
121}
122
128{
129public:
132 explicit attachment_transform(const node& n)
133 : m_node(n) { }
134#ifndef BOOST_NO_RVALUE_REFERENCES
138 : m_node(std::move(other.m_node)) { }
139#endif
144 { return attachment(property_bag(m_node.lookup(row.get_row_id()))); }
145
147 : m_node(other.m_node) { }
148
149private:
150 node m_node;
151};
152
158{
159public:
160 // property access
163 std::wstring get_name() const
164 { return m_row.read_prop<std::wstring>(PR_DISPLAY_NAME_W); }
168 { return static_cast<recipient_type>(m_row.read_prop<ulong>(PR_RECIPIENT_TYPE)); }
171 std::wstring get_address_type() const
172 { return m_row.read_prop<std::wstring>(PR_ADDRTYPE_W); }
175 std::wstring get_email_address() const
176 { return m_row.read_prop<std::wstring>(0x39fe); }
179 bool has_email_address() const
180 { return m_row.prop_exists(0x39fe); }
183 std::wstring get_account_name() const
184 { return m_row.read_prop<std::wstring>(PR_ACCOUNT_W); }
187 bool has_account_name() const
188 { return m_row.prop_exists(PR_ACCOUNT_W); }
189
190 // lower layer access
194 { return m_row; }
197 { return m_row; }
198
199private:
200 recipient& operator=(const recipient&); // = delete
201 friend struct recipient_transform;
202
203 explicit recipient(const const_table_row& row)
204 : m_row(row) { }
205 const_table_row m_row;
206};
207
217
229{
230public:
232 typedef boost::transform_iterator<attachment_transform, const_table_row_iter> attachment_iterator;
234 typedef boost::transform_iterator<recipient_transform, const_table_row_iter> recipient_iterator;
235
238 explicit message(const node& n)
239 : m_bag(n) { }
240 message(const message& other);
241
242#ifndef BOOST_NO_RVALUE_REFERENCES
244 : m_bag(std::move(other.m_bag)), m_attachment_table(std::move(other.m_attachment_table)), m_recipient_table(std::move(other.m_recipient_table)) { }
245#endif
246
247 // subobject discovery/enumeration
251 { return boost::make_transform_iterator(get_attachment_table().begin(), attachment_transform(m_bag.get_node())); }
255 { return boost::make_transform_iterator(get_attachment_table().end(), attachment_transform(m_bag.get_node())); }
259 { return boost::make_transform_iterator(get_recipient_table().begin(), recipient_transform()); }
263 { return boost::make_transform_iterator(get_recipient_table().end(), recipient_transform()); }
264
265 // property access
268 std::wstring get_subject() const;
271 bool has_subject() const
272 { return m_bag.prop_exists(0x37); }
275 std::wstring get_body() const
276 { return m_bag.read_prop<std::wstring>(PR_BODY_W); }
287 { return m_bag.open_prop_stream(0x1000); }
290 size_t body_size() const
291 { return m_bag.size(0x1000); }
294 bool has_body() const
295 { return m_bag.prop_exists(0x1000); }
298 std::wstring get_html_body() const
299 { return m_bag.read_prop<std::wstring>(0x1013); }
313 size_t html_body_size() const
314 { return m_bag.size(0x1013); }
317 bool has_html_body() const
318 { return m_bag.prop_exists(0x1013); }
319 // \brief Get the total size of this message
321 size_t size() const
322 {
323 size_t size = 0;
325
326 if (size_type == prop_type_long) {
328 } else if (size_type == prop_type_longlong) {
330 }
331
332 return size;
333 }
336 size_t get_attachment_count() const;
339 size_t get_recipient_count() const;
340
341 // lower layer access
345 { return m_bag; }
348 { return m_bag; }
356 const table& get_attachment_table() const;
358 const table& get_recipient_table() const;
359
363 { return m_bag.get_node().get_id(); }
364
365private:
366 message& operator=(const message&); // = delete
367
368 property_bag m_bag;
369 mutable std::shared_ptr<table> m_attachment_table;
370 mutable std::shared_ptr<table> m_recipient_table;
371};
372
374{
375public:
377 : m_db(db) { }
379 { return message(m_db->lookup_node(row.get_row_id())); }
380
381private:
382 shared_db_ptr m_db;
383};
384
386{
387public:
389 : m_db(db) { }
391 { return message(node(m_db, info)); }
392
393private:
394 shared_db_ptr m_db;
395};
396
397} // end namespace pstsdk
398
399inline std::wstring pstsdk::attachment::get_filename() const
400{
401 try
402 {
403 return m_bag.read_prop<std::wstring>(PR_ATTACH_LONG_FILENAME_W);
404 }
406 {
407 return m_bag.read_prop<std::wstring>(PR_ATTACH_FILENAME_W);
408 }
409}
410
412{
413 if(!is_message())
414 throw std::bad_cast();
415
416 std::vector<byte> buffer = get_bytes();
418
419 return message(m_bag.get_node().lookup(psubo->nid));
420}
421
423: m_bag(other.m_bag)
424{
425 if(other.m_attachment_table)
426 m_attachment_table.reset(new table(*other.m_attachment_table));
427 if(other.m_recipient_table)
428 m_recipient_table.reset(new table(*other.m_recipient_table));
429}
430
432{
433 if(!m_attachment_table)
434 m_attachment_table.reset(new table(m_bag.get_node().lookup(nid_attachment_table)));
435
436 return *m_attachment_table;
437}
438
440{
441 if(!m_recipient_table)
442 m_recipient_table.reset(new table(m_bag.get_node().lookup(nid_recipient_table)));
443
444 return *m_recipient_table;
445}
446
448{
449 return const_cast<table&>(const_cast<const message*>(this)->get_attachment_table());
450}
451
453{
454 return const_cast<table&>(const_cast<const message*>(this)->get_recipient_table());
455}
456
458{
459 size_t count = 0;
460 try
461 {
462 count = get_attachment_table().size();
463 }
464 catch (const key_not_found<node_id>&) { }
465
466 return count;
467}
468
470{
471 size_t count = 0;
472 try
473 {
474 count = get_recipient_table().size();
475 }
476 catch (const key_not_found<node_id>&) { }
477
478 return count;
479}
480
481inline std::wstring pstsdk::message::get_subject() const
482{
483 std::wstring buffer = m_bag.read_prop<std::wstring>(PR_SUBJECT_W);
484
486 {
487 // Skip the second chracter as well
488 return buffer.substr(2);
489 }
490 else
491 {
492 return buffer;
493 }
494}
495
496#endif
Defines a transform from a row to an attachment object.
Definition message.h:128
attachment_transform(const attachment_transform &other)
Definition message.h:146
attachment_transform(const node &n)
Construct the transform object.
Definition message.h:132
attachment_transform(attachment_transform &&other)
Move constructor for transform objects.
Definition message.h:137
attachment operator()(const const_table_row &row) const
Perform the transform.
Definition message.h:143
Encapsulates an attachment to a message.
Definition message.h:37
message open_as_message() const
Interpret this attachment as a message.
Definition message.h:411
std::vector< byte > get_bytes() const
Get the attachment data, as a blob.
Definition message.h:48
const property_bag & get_property_bag() const
Get the property bag backing this attachment.
Definition message.h:93
size_t size() const
Read the size of this attachment.
Definition message.h:67
bool is_message() const
Returns if this attachment is actually an embedded message.
Definition message.h:80
std::wstring get_filename() const
Get the filename of this attachment.
Definition message.h:399
hnid_stream_device open_byte_stream()
Open a stream of the attachment data.
Definition message.h:59
size_t content_size() const
Read the size of the content in this attachment.
Definition message.h:73
property_bag & get_property_bag()
Get the property bag backing this attachment.
Definition message.h:90
heap_id get_id() const
Return the heap_id of this bth_node.
Definition heap.h:322
Contains references to other bth_node allocations.
Definition heap.h:364
T read_prop(prop_id id) const
Read a property as a given type.
Definition object.h:188
An abstraction of a table row.
Definition table.h:51
bool prop_exists(prop_id id) const
Indicates the existance of a given property on this object.
Definition table.h:438
Defines a stream device which can wrap one of the two prop sources.
Definition object.h:56
message_transform_info(const shared_db_ptr &db)
Definition message.h:388
message operator()(const node_info &info) const
Definition message.h:390
message_transform_row(const shared_db_ptr &db)
Definition message.h:376
message operator()(const const_table_row &row) const
Definition message.h:378
Represents a message in a PST file.
Definition message.h:229
size_t size() const
Definition message.h:321
size_t body_size() const
Size of the body, in bytes.
Definition message.h:290
table & get_attachment_table()
Get the attachment table of this message.
Definition message.h:447
size_t get_recipient_count() const
Get the number of recipients on this message.
Definition message.h:469
std::wstring get_body() const
Get the body of this message.
Definition message.h:275
std::wstring get_subject() const
Get the subject of this message.
Definition message.h:481
boost::transform_iterator< attachment_transform, const_table_row_iter > attachment_iterator
Attachment iterator type; a transform iterator over a table row iterator.
Definition message.h:232
bool has_html_body() const
Checks to see if this message has a HTML body.
Definition message.h:317
recipient_iterator recipient_end() const
Get the end recipient iterator.
Definition message.h:262
bool has_body() const
Checks to see if this message has a body.
Definition message.h:294
boost::transform_iterator< recipient_transform, const_table_row_iter > recipient_iterator
Recipient iterator type; a transform iterator over a table row iterator.
Definition message.h:234
recipient_iterator recipient_begin() const
Get an iterator to the first recipient of this message.
Definition message.h:258
std::wstring get_html_body() const
Get the HTML body of this message.
Definition message.h:298
size_t html_body_size() const
Size of the HTML body, in bytes.
Definition message.h:313
hnid_stream_device open_html_body_stream()
Get the HTML body of this message.
Definition message.h:309
attachment_iterator attachment_begin() const
Get an iterator to the first message on this message.
Definition message.h:250
bool has_subject() const
Check to see if a subject is set on this message.
Definition message.h:271
property_bag & get_property_bag()
Get the property bag backing this message.
Definition message.h:344
hnid_stream_device open_body_stream()
Get the body of this message.
Definition message.h:286
message(const node &n)
Construct a message object.
Definition message.h:238
message(message &&other)
Definition message.h:243
table & get_recipient_table()
Get the recipient table of this message.
Definition message.h:452
node_id get_id() const
Get the node_id of this message.
Definition message.h:362
const property_bag & get_property_bag() const
Get the property bag backing this message.
Definition message.h:347
size_t get_attachment_count() const
Get the number of attachments on this message.
Definition message.h:457
attachment_iterator attachment_end() const
Get the end attachment iterator.
Definition message.h:254
An in memory representation of the "node" concept in a PST data file.
Definition node.h:320
node lookup(node_id id) const
Lookup a subnode by node id.
Definition node.h:461
Property Context (PC) Implementation.
Definition propbag.h:41
prop_type get_prop_type(prop_id id) const
Get the property type of a given prop_id.
Definition propbag.h:69
const node & get_node() const
Get the node underlying this property_bag.
Definition propbag.h:77
bool prop_exists(prop_id id) const
Indicates the existance of a given property on this object.
Definition propbag.h:181
hnid_stream_device open_prop_stream(prop_id id)
Creates a stream device over a property on this object.
Definition propbag.h:233
size_t size(prop_id id) const
Returns the total size of a variable length property.
Definition propbag.h:223
A recipient of a message.
Definition message.h:158
std::wstring get_email_address() const
Get the email address of the recipient.
Definition message.h:175
std::wstring get_account_name() const
Get the name of the recipients account.
Definition message.h:183
recipient_type get_type() const
Get the type of this recipient.
Definition message.h:167
std::wstring get_name() const
Get the display name of this recipient.
Definition message.h:163
std::wstring get_address_type() const
Get the address type of the recipient.
Definition message.h:171
const const_table_row & get_property_row() const
Get the property row underying this recipient object.
Definition message.h:196
const_table_row & get_property_row()
Get the property row underying this recipient object.
Definition message.h:193
bool has_email_address() const
Checks to see if this recipient has an email address.
Definition message.h:179
bool has_account_name() const
Checks to see if this recipient has an account name.
Definition message.h:187
The actual table object that clients reference.
Definition table.h:308
size_t size() const
Get the number of rows in this table.
Definition table.h:362
Database interface.
const byte message_subject_prefix_lead_byte
A sentinel byte which indicates the message subject contains a prefix.
Definition primitives.h:344
recipient_type
The different recipient types as defined by MAPI.
Definition primitives.h:331
boost::uint32_t uint
Definition primitives.h:67
ulong node_id
Definition primitives.h:86
boost::uint32_t ulong
Definition primitives.h:68
@ nid_recipient_table
Definition primitives.h:197
@ nid_attachment_table
Definition primitives.h:196
@ prop_type_longlong
Definition primitives.h:310
@ prop_type_long
Definition primitives.h:297
std::ostream & operator<<(std::ostream &out, const attachment &attach)
operator<< overload for writing an attachment to an ostream
Definition message.h:116
#define PR_ADDRTYPE_W
Definition mapitags.h:362
#define PR_SUBJECT_W
Definition mapitags.h:98
#define PR_DISPLAY_NAME_W
Definition mapitags.h:359
#define PR_ATTACH_DATA_OBJ
Definition mapitags.h:458
#define PR_ATTACH_METHOD
Definition mapitags.h:467
#define PR_RECIPIENT_TYPE
Definition mapitags.h:277
#define PR_BODY_W
Definition mapitags.h:234
#define PR_ATTACH_FILENAME_W
Definition mapitags.h:464
#define PR_ATTACH_SIZE
Definition mapitags.h:336
#define PR_MESSAGE_SIZE
Definition mapitags.h:312
#define PR_ATTACH_LONG_FILENAME_W
Definition mapitags.h:468
#define PR_ACCOUNT_W
Definition mapitags.h:492
Contains the definition of all in memory representations of disk structures.
Definition disk.h:19
std::shared_ptr< db_context > shared_db_ptr
Node and Block definitions.
Primitive structures defined by MS-PST and MAPI.
Property Bag (or Property Context, or PC) implementation.
An in memory, database format agnostic version of disk::nbt_leaf_entry.
Defines a transform from a row to a recipient object.
Definition message.h:213
recipient operator()(const_table_row row) const
Definition message.h:214
Table (or Table Context, or TC) implementation.