PST File Format SDK v0.4
Loading...
Searching...
No Matches
nameid.h
Go to the documentation of this file.
1
5
6#ifndef PSTSDK_LTP_NAMEID_H
7#define PSTSDK_LTP_NAMEID_H
8
9#include <string>
10#include <algorithm>
11
13
15
16#include "pstsdk/ltp/propbag.h"
17
18namespace pstsdk
19{
20
23
31{
32public:
36 named_prop(const guid& g, long id)
37 : m_guid(g), m_is_string(false), m_id(id) { }
41 named_prop(const guid& g, const std::wstring& name)
42 : m_guid(g), m_is_string(true), m_name(name) { }
43
46 const guid& get_guid() const { return m_guid; }
49 bool is_string() const { return m_is_string; }
53 long get_id() const { return m_id; }
57 const std::wstring& get_name() const { return m_name; }
58
59private:
60 guid m_guid;
61 bool m_is_string;
62 long m_id;
63 std::wstring m_name;
64};
65
75class name_id_map : private boost::noncopyable
76{
77public:
83 : m_bag(db->lookup_node(nid_name_id_map)), m_buckets(m_bag.read_prop<slong>(0x1)), m_entry_stream(m_bag.open_prop_stream(0x3)), m_guid_stream(m_bag.open_prop_stream(0x2)), m_string_stream(m_bag.open_prop_stream(0x4)) { }
84
89 bool name_exists(const guid& g, const std::wstring& name) const
90 { return named_prop_exists(named_prop(g, name)); }
95 bool id_exists(const guid& g, long id) const
96 { return named_prop_exists(named_prop(g, id)); }
100 bool named_prop_exists(const named_prop& p) const;
104 bool prop_id_exists(prop_id id) const;
107 size_t get_prop_count() const;
108
111 std::vector<prop_id> get_prop_list() const;
112
118 prop_id lookup(const guid& g, const std::wstring& name) const
119 { return lookup(named_prop(g, name)); }
125 prop_id lookup(const guid& g, long id) const
126 { return lookup(named_prop(g, id)); }
131 prop_id lookup(const named_prop& p) const;
132
137 named_prop lookup(prop_id id) const;
138
139private:
140 // helper functions
141 named_prop construct(const disk::nameid& entry) const;
142 named_prop construct(ulong index) const;
147 guid read_guid(ushort guid_index) const;
148 ushort get_guid_index(const guid& g) const;
149 std::wstring read_wstring(ulong string_offset) const;
150 ulong compute_hash_base(const named_prop& n) const;
151 ulong compute_hash_value(ushort guid_index, const named_prop& n) const
152 { return (n.is_string() ? ((guid_index << 1) | 1) : (guid_index << 1)) ^ compute_hash_base(n); }
153 prop_id get_bucket_prop(ulong hash_value) const
154 { return static_cast<prop_id>((hash_value % m_buckets) + 0x1000); }
155
156 property_bag m_bag;
157 ulong m_buckets;
158 mutable prop_stream m_entry_stream;
159 mutable prop_stream m_guid_stream;
160 mutable prop_stream m_string_stream;
161};
162
163inline pstsdk::named_prop pstsdk::name_id_map::construct(const disk::nameid& entry) const
164{
165 if(nameid_is_string(entry))
166 return named_prop(read_guid(disk::nameid_get_guid_index(entry)), read_wstring(entry.string_offset));
167 else
168 return named_prop(read_guid(disk::nameid_get_guid_index(entry)), entry.id);
169}
170
171inline pstsdk::named_prop pstsdk::name_id_map::construct(ulong index) const
172{
173 disk::nameid entry;
174 m_entry_stream.seekg(index * sizeof(disk::nameid), std::ios_base::beg);
175 m_entry_stream.read((char*)&entry, sizeof(entry));
176 return construct(entry);
177}
178
179inline pstsdk::guid pstsdk::name_id_map::read_guid(ushort guid_index) const
180{
181 if(guid_index == 0)
182 return ps_none;
183 if(guid_index == 1)
184 return ps_mapi;
185 if(guid_index == 2)
186 return ps_public_strings;
187
188 guid g;
189 m_guid_stream.seekg((guid_index-3) * sizeof(guid), std::ios_base::beg);
190 m_guid_stream.read((char*)&g, sizeof(g));
191 return g;
192}
193
194inline pstsdk::ushort pstsdk::name_id_map::get_guid_index(const guid& g) const
195{
196 if(memcmp(&g, &ps_none, sizeof(g)) == 0)
197 return 0;
198 if(memcmp(&g, &ps_mapi, sizeof(g)) == 0)
199 return 1;
200 if(memcmp(&g, &ps_public_strings, sizeof(g)) == 0)
201 return 2;
202
203 guid g_disk;
204 ushort num = 0;
205 m_guid_stream.seekg(0, std::ios_base::beg);
206 while(m_guid_stream.read((char*)&g_disk, sizeof(g_disk)))
207 {
208 if(memcmp(&g, &g_disk, sizeof(g)) == 0)
209 return num + 3;
210 ++num;
211 }
212
213 // didn't find it
214 m_guid_stream.clear();
215 throw key_not_found<guid>(g);
216}
217
218inline std::wstring pstsdk::name_id_map::read_wstring(ulong string_offset) const
219{
220 m_string_stream.seekg(string_offset, std::ios_base::beg);
221
222 ulong size;
223 m_string_stream.read((char*)&size, sizeof(size));
224
225 std::vector<byte> buffer(size);
226 m_string_stream.read(reinterpret_cast<char *>(&buffer[0]), size);
227
228 return bytes_to_wstring(buffer);
229}
230
231inline pstsdk::ulong pstsdk::name_id_map::compute_hash_base(const named_prop& n) const {
232 if(n.is_string())
233 {
234 std::vector<byte> bytes(wstring_to_bytes(n.get_name()));
235 return disk::compute_crc(&bytes[0], bytes.size());
236 }
237 else
238 {
239 return n.get_id();
240 }
241}
242
244{
245 try
246 {
247 lookup(p);
248 return true;
249 }
250 catch(std::exception&)
251 {
252 return false;
253 }
254}
255
257{
258 if(id >= 0x8000)
259 return static_cast<size_t>((id - 0x8000)) < get_prop_count();
260
261 // id < 0x8000 is a ps_mapi prop
262 return true;
263}
264
265inline std::vector<prop_id> pstsdk::name_id_map::get_prop_list() const
266{
267 disk::nameid entry;
268 std::vector<prop_id> props;
269
270 m_entry_stream.seekg(0, std::ios_base::beg);
271 while(m_entry_stream.read((char*)&entry, sizeof(entry)))
272 props.push_back(nameid_get_prop_index(entry) + 0x8000);
273
274 m_entry_stream.clear();
275
276 return props;
277}
278
280{
281 m_entry_stream.seekg(0, std::ios_base::end);
282
283 return static_cast<size_t>(m_entry_stream.tellg()) / sizeof(disk::nameid);
284}
285
287{
289
290 try
291 {
292 guid_index = get_guid_index(p.get_guid());
293 }
294 catch(key_not_found<guid>&)
295 {
297 }
298
299 // special handling of ps_mapi
300 if(guid_index == 1)
301 {
302 if(p.is_string()) throw key_not_found<named_prop>(p);
303 if(p.get_id() >= 0x8000) throw key_not_found<named_prop>(p);
304 return static_cast<prop_id>(p.get_id());
305 }
306
307 ulong hash_value = compute_hash_value(guid_index, p);
308 ulong hash_base = compute_hash_base(p);
309
310 if(!m_bag.prop_exists(get_bucket_prop(hash_value)))
312
313 prop_stream bucket(const_cast<name_id_map*>(this)->m_bag.open_prop_stream(get_bucket_prop(hash_value)));
315 while(bucket.read((char*)&entry, sizeof(entry)))
316 {
317 if( (entry.hash_base == hash_base) &&
318 (disk::nameid_is_string(entry) == p.is_string()) &&
320 )
321 {
322 // just double check the string..
323 if(p.is_string())
324 {
325 if(construct(disk::nameid_get_prop_index(entry)).get_name() != p.get_name())
326 continue;
327 }
328
329 // found it!
330 return disk::nameid_get_prop_index(entry) + 0x8000;
331 }
332 }
333
335}
336
338{
339 if(id < 0x8000)
340 return named_prop(ps_mapi, id);
341
342 ulong index = id - 0x8000;
343
344 if(index > get_prop_count())
345 throw key_not_found<prop_id>(id);
346
347 return construct(index);
348}
349
350} // end namespace pstsdk
351
352#endif
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
A named property map abstraction.
Definition nameid.h:76
prop_id lookup(const guid &g, long id) const
Get the associated prop_id of the named property.
Definition nameid.h:125
std::vector< prop_id > get_prop_list() const
Get all of the prop_ids which have a named_prop mapping in this store.
Definition nameid.h:265
name_id_map(const shared_db_ptr &db)
Construct a name_id_map for the given store.
Definition nameid.h:82
bool id_exists(const guid &g, long id) const
Query if a given named prop exists.
Definition nameid.h:95
bool named_prop_exists(const named_prop &p) const
Query if a given named prop exists.
Definition nameid.h:243
prop_id lookup(const guid &g, const std::wstring &name) const
Get the associated prop_id of the named property.
Definition nameid.h:118
size_t get_prop_count() const
Get the total count of named property mappings in this store.
Definition nameid.h:279
bool name_exists(const guid &g, const std::wstring &name) const
Query if a given named prop exists.
Definition nameid.h:89
bool prop_id_exists(prop_id id) const
Query if a given prop_id has a named_prop mapped to it.
Definition nameid.h:256
A named property.
Definition nameid.h:31
long get_id() const
Get the numerical id of this property.
Definition nameid.h:53
const guid & get_guid() const
Get the namespace GUID of which this named prop is a member.
Definition nameid.h:46
bool is_string() const
Return true if this is a string named prop.
Definition nameid.h:49
const std::wstring & get_name() const
Get the name of this property.
Definition nameid.h:57
named_prop(const guid &g, long id)
Construct a named prop from a guid and an id.
Definition nameid.h:36
named_prop(const guid &g, const std::wstring &name)
Construct a named prop from a guid and a string.
Definition nameid.h:41
Database interface.
ushort nameid_get_prop_index(const nameid &n)
Returns the index of a given nameid structure.
Definition disk.h:1585
bool nameid_is_string(const nameid &n)
Returns true if the nameid structure is named by a string.
Definition disk.h:1599
ushort nameid_get_guid_index(const nameid &n)
Returns the index into the guid stream of the guid of a given nameid structure.
Definition disk.h:1592
boost::iostreams::stream< hnid_stream_device > prop_stream
The actual property stream, defined using the boost iostream library and the hnid_stream_device.
Definition object.h:81
boost::int32_t slong
Definition primitives.h:69
boost::uint32_t ulong
Definition primitives.h:68
const guid ps_public_strings
The PS_PUBLIC_STRINGS guid.
Definition primitives.h:382
const guid ps_none
The NULL guid.
Definition primitives.h:372
boost::uint16_t ushort
Definition primitives.h:73
ushort prop_id
Definition primitives.h:93
const guid ps_mapi
The PS_MAPI guid.
Definition primitives.h:377
@ nid_name_id_map
Contains the named prop mappings.
Definition primitives.h:172
std::wstring bytes_to_wstring(const std::vector< byte > &bytes)
Convert an array of bytes to a std::wstring.
Definition util.h:280
std::vector< byte > wstring_to_bytes(const std::wstring &wstr)
Convert a std::wstring to an array of bytes.
Definition util.h:343
ulong compute_crc(const void *pdata, ulong cb)
Compute the CRC of a block of data.
Definition disk.h:1634
Contains the definition of all in memory representations of disk structures.
Definition disk.h:19
std::shared_ptr< db_context > shared_db_ptr
Primitive structures defined by MS-PST and MAPI.
Property Bag (or Property Context, or PC) implementation.
A modified nameid structure used in the hash buckets.
Definition disk.h:1571
ulong hash_base
For numeric named props, this is just the id. Hash value of string props.
Definition disk.h:1572
Defines a id to name mapping.
Definition disk.h:1553
A Win32 GUID structure.
Definition primitives.h:353