15#ifndef PSTSDK_PST_DELETE_H
16#define PSTSDK_PST_DELETE_H
41const slong mapi_message_read = 0x1;
103 property_bag bag(db->lookup_node(nid));
104 if(!bag.prop_exists(
id))
107 value = bag.read_prop<
slong>(id);
110 catch(key_not_found<node_id>&)
119 std::vector<row_id> rows;
123 table tc(db->lookup_node(nid));
124 for(
size_t i = 0; i < tc.size(); ++i)
125 rows.push_back(tc[i].get_row_id());
127 catch(key_not_found<node_id>&) { }
134 std::vector<row_id> rows;
136 table tc(db->lookup_node(owner).lookup(sub));
137 for(
size_t i = 0; i < tc.size(); ++i)
138 rows.push_back(tc[i].get_row_id());
146inline std::vector<node_id> search_contents_tables(
const shared_db_ptr& db)
148 std::vector<node_id> tables;
149 std::shared_ptr<nbt_page> root = db->read_nbt_root();
159 tables.push_back((*i).id);
166inline void sweep_search_folders(db_writer<T>& writer,
const std::vector<node_id>& tables,
169 for(
size_t i = 0; i < tables.size(); ++i)
171 try { tc_remove_row(writer, tables[i], message); }
172 catch(key_not_found<row_id>&) { }
183inline bool remove_message_row(db_writer<T>& writer,
node_id folder,
node_id message,
bool& associated)
191 catch(key_not_found<row_id>&) { }
199 catch(key_not_found<row_id>&) { }
205inline void delete_message_impl(
const std::shared_ptr<database_impl<T> >& db,
node_id nid)
207 const node_info info = db->lookup_node_info(nid);
208 const node_id folder = info.parent_id;
214 const bool unread = has_flags && (flags & mapi_message_read) == 0;
216 slong content_count = 0;
217 slong unread_count = 0;
218 slong associated_count = 0;
219 const bool has_content = try_read_long(db, folder,
PR_CONTENT_COUNT, content_count);
220 const bool has_unread = try_read_long(db, folder,
PR_CONTENT_UNREAD, unread_count);
223 const std::vector<node_id> search = search_contents_tables(db);
225 db_writer<T> writer(db);
227 bool associated =
false;
228 const bool removed = folder != 0 && remove_message_row(writer, folder, nid, associated);
230 if(removed && associated && has_associated && associated_count > 0)
233 if(removed && !associated && has_content && content_count > 0)
236 if(removed && !associated && unread && has_unread && unread_count > 0)
239 sweep_search_folders(writer, search, nid);
241 writer.delete_node(nid);
246inline void delete_attachment_impl(
const std::shared_ptr<database_impl<T> >& db,
249 db_writer<T> writer(db);
250 const typename db_writer<T>::data_ref message = writer.node_ref(message_nid);
253 throw key_not_found<node_id>(attachment_nid);
255 const typename db_writer<T>::data_ref table =
258 tc_remove_row(writer, table, attachment_nid);
259 writer.subnode_remove(message.sub, attachment_nid);
265 catch(key_not_found<node_id>&) { }
270 catch(key_not_found<prop_id>&) { }
277inline ulonglong wipe_impl(
const std::shared_ptr<database_impl<T> >& db)
279 db_writer<T> writer(db);
280 const ulonglong wiped = writer.wipe_free_space();
286inline void delete_folder_contents(db_writer<T>& writer,
const std::shared_ptr<database_impl<T> >& db,
287 node_id folder,
const std::vector<node_id>& search,
288 std::set<node_id>& seen)
291 if(!seen.insert(folder).second)
294 const std::vector<row_id> subfolders =
297 for(
size_t i = 0; i < subfolders.size(); ++i)
298 delete_folder_contents(writer, db, subfolders[i], search, seen);
302 const std::vector<row_id> messages =
304 const std::vector<row_id> associated =
307 for(
size_t i = 0; i < messages.size(); ++i)
309 sweep_search_folders(writer, search, (
node_id)messages[i]);
310 try { writer.delete_node(messages[i]); }
311 catch(key_not_found<node_id>&) { }
314 for(
size_t i = 0; i < associated.size(); ++i)
316 try { writer.delete_node(associated[i]); }
317 catch(key_not_found<node_id>&) { }
323 for(
size_t i = 0; i <
sizeof(tables) /
sizeof(tables[0]); ++i)
325 try { writer.delete_node(folder_table(folder, tables[i])); }
326 catch(key_not_found<node_id>&) { }
329 try { writer.delete_node(folder); }
330 catch(key_not_found<node_id>&) { }
334inline void delete_folder_impl(
const std::shared_ptr<database_impl<T> >& db,
node_id nid)
336 const node_info info = db->lookup_node_info(nid);
337 const node_id parent = info.parent_id;
339 const size_t siblings =
341 const std::vector<node_id> search = search_contents_tables(db);
343 db_writer<T> writer(db);
348 catch(key_not_found<row_id>&) { }
354 catch(key_not_found<prop_id>&) { }
358 std::set<node_id> seen;
359 delete_folder_contents(writer, db, nid, search, seen);
368 if(std::shared_ptr<large_pst> unicode = std::dynamic_pointer_cast<large_pst>(db))
369 return detail::delete_message_impl(unicode, nid);
370 if(std::shared_ptr<small_pst> ansi = std::dynamic_pointer_cast<small_pst>(db))
371 return detail::delete_message_impl(ansi, nid);
373 throw invalid_format();
377 node_id attachment_nid)
379 if(std::shared_ptr<large_pst> unicode = std::dynamic_pointer_cast<large_pst>(db))
380 return detail::delete_attachment_impl(unicode, message_nid, attachment_nid);
381 if(std::shared_ptr<small_pst> ansi = std::dynamic_pointer_cast<small_pst>(db))
382 return detail::delete_attachment_impl(ansi, message_nid, attachment_nid);
384 throw invalid_format();
389 if(std::shared_ptr<large_pst> unicode = std::dynamic_pointer_cast<large_pst>(db))
390 return detail::wipe_impl(unicode);
391 if(std::shared_ptr<small_pst> ansi = std::dynamic_pointer_cast<small_pst>(db))
392 return detail::wipe_impl(ansi);
394 throw invalid_format();
399 if(std::shared_ptr<large_pst> unicode = std::dynamic_pointer_cast<large_pst>(db))
400 return detail::delete_folder_impl(unicode, nid);
401 if(std::shared_ptr<small_pst> ansi = std::dynamic_pointer_cast<small_pst>(db))
402 return detail::delete_folder_impl(ansi, nid);
404 throw invalid_format();
Contains references to other bth_node allocations.
const_iterator begin() const
Returns a STL style iterator positioned at the first entry.
The exceptions used by pstsdk.
boost::uint64_t ulonglong
ulong get_nid_index(node_id id)
Get a node index from a node id.
nid_type
Different node types found in a PST file.
nid_type get_nid_type(node_id id)
Get a node type from a node id.
#define make_nid(nid_type, nid_index)
Construct a node_id (NID) from a node type and index.
@ nid_type_hierarchy_table
@ nid_type_contents_table
@ nid_type_search_contents_table
@ nid_type_associated_contents_table
@ nid_all_message_search_contents
In place edits of heaps, BTHs, property contexts and table contexts.
Contains the definition of all in memory representations of disk structures.
std::shared_ptr< db_context > shared_db_ptr
const_btree_node_iter< node_id, node_info > const_nodeinfo_iterator
In place edits of an open store.
Primitive structures defined by MS-PST and MAPI.
Property Bag (or Property Context, or PC) implementation.
Table (or Table Context, or TC) implementation.