/
iNotePrecipitator.php
448 lines (359 loc) · 14.1 KB
/
iNotePrecipitator.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
<?php
/**
* iNotePrecipitator.php
*
* iCloud Notes Access Functions Class
*
* @version 0.1.0
*
* @author Avi Ginsberg
*
*/
class iNotePrecipitator
{
protected
/**
* IMAP connection object.
* @var object
*/
$imap,
/**
* The user's email address.
* @var string
*/
$email,
/**
* The user's username (everything before the @ symbol in the email address.) Derived from $email.
* @var string
*/
$username,
/**
* The FQDN of the user's email address (everything after the @ symbol in the email address.) Derived from $email.
* @var string
*/
$domain,
/**
* Associative array containing all regular notes from the user's icloud account. (regular notes are non-deleted notes)
* @var array
*/
$regular_notes,
/**
* Associative array containing all deleted notes from the user's icloud account.
* @var array
*/
$deleted_notes,
/**
* Associative array containing various properties of the notes storage mailbox including: Date, Driver, Mailbox name, Number of notes, Notes storage mailbox size.
* @var array
*/
$notes_mailbox_info,
/**
* Associative array containing all note header data.
* @var array
*/
$note_headers;
/**
* Boolean representing login success. Is set to TRUE when an icloud login has been completed successfully.
* @var boolean
*/
public $login_success = FALSE;
/**
* Constructs a new iNotePrecipitator object.
*
* @param string $email The email address used to log into the iCloud account.
* @param string $password The password used to log into the iCloud account.
*/
function __construct($email, $password)
{
//explode email address into username and domain
$this->username = explode("@",$email)[0];
$this->domain = explode("@",$email)[1];
//Open the connection to iCloud notes mailbox
$this->imap = imap_open('{imap.mail.me.com:993/imap/ssl}Notes', $this->username, $password);
//set the login status
if (!$this->imap) {
$this->login_success = FALSE;
} else {
$this->login_success = TRUE;
}
//get our mailbox info
$this->notes_mailbox_info = get_object_vars(imap_mailboxmsginfo($this->imap));
}
/**
* Get the total number of notes in the iCloud account.
*
* @return int <u>Description:</u><br>Returns total number of notes (deleted and regular).
*/
function Get_Total_Notes_Count()
{
return $this->notes_mailbox_info['Nmsgs'];
}
/**
* Get the number of regular (non-deleted) notes in the iCloud account.
*
* @return int <u>Description:</u><br>Returns number of regular notes.
*/
function Get_Regular_Notes_Count()
{
return $this->notes_mailbox_info['Nmsgs'] - $this->notes_mailbox_info['Deleted'];
}
/**
* Get the number of deleted notes in the iCloud account.
*
* @return int <u>Description:</u><br>Returns number of deleted notes.
*/
function Get_Deleted_Notes_Count()
{
return $this->notes_mailbox_info['Deleted'];
}
/**
* Get the header data of a note and returns it as an associative array.
*
* @param int $ID_Num The numerical ID of the note.
*
* @return Array <u>Description:</u><br>An associative array containing note header data.<br>Common values are "Date", "Subject", and "Size". Other values may be present. These values differ based on iOS version that created the note.
*/
function Get_Note_Header_By_ID_Num($ID_Num)
{
//if we already have the header data, return the requested header
if (isset($this->note_headers)) {
return $this->note_headers[$ID_Num - 1];
//get all note header data and store it for future use
} else {
$this->note_headers = Array();
for ($notenum_loop = 1; $notenum_loop <= $this->Get_Total_Notes_Count(); $notenum_loop++) {
$this->note_headers[$notenum_loop - 1] = get_object_vars(imap_header($this->imap, $notenum_loop));
}
return $this->note_headers[$ID_Num - 1];
}
}
/**
* Get the header data and body text of a note and returns it as an associative array.
*
* @param int $ID_Num The numerical ID of the note.
*
* @return Array <u>Description:</u><br>An associative array containing standardized note header data and note body text.<br>Values are "Date", "H-Date", "Unix-Date", "Subject", "ID-Num", "Size", and "Note".
*/
function Get_Note_With_Header_Data_By_ID_Num($ID_Num)
{
return Array(
"Date" => trim($this->Get_Note_Header_By_ID_Num($ID_Num)['Date']),
"H-Date" => trim($this->Get_Note_Header_By_ID_Num($ID_Num)['MailDate']),
"Unix-Date" => trim($this->Get_Note_Header_By_ID_Num($ID_Num)['udate']),
"Subject" => trim($this->Get_Note_Header_By_ID_Num($ID_Num)['Subject']),
"ID-Num" => trim($this->Get_Note_Header_By_ID_Num($ID_Num)['Msgno']),
"Size" => trim($this->Get_Note_Header_By_ID_Num($ID_Num)['Size']),
"Note" => trim(quoted_printable_decode(imap_fetchbody($this->imap, $ID_Num, "1"))));
}
/**
* Get the body text of a specific note.
*
* @param int $ID_Num The numerical ID of the note.
*
* @return string <u>Description:</u><br>The body text of the note.
*/
function Get_Note_Body_By_ID_Num($ID_Num)
{
return trim(quoted_printable_decode(imap_fetchbody($this->imap, $ID_Num, "1")));
}
/**
* Get the subject of a specific note.
*
* @param int $ID_Num The numerical ID of the note.
*
* @return string <u>Description:</u><br>The subject of the note.
*/
function Get_Note_Subject_By_ID_Num($ID_Num)
{
return trim($this->Get_Note_Header_By_ID_Num($ID_Num)['Subject']);
}
/**
* Get the size (in bytes) of a specific note.
*
* @param int $ID_Num The numerical ID of the note.
*
* @return int <u>Description:</u><br>The size (in bytes) of the note.
*/
function Get_Note_Size_By_ID_Num($ID_Num)
{
return trim($this->Get_Note_Header_By_ID_Num($ID_Num)['Size']);
}
/**
* Check if the a note exists (based on note ID).
*
* @param int $ID_Num The numerical ID of the note.
*
* @return boolean <u>Description:</u><br>TRUE if the note exists. FALSE if the note does NOT exist.
*/
function Check_If_Note_Exists_By_ID_Num($ID_Num)
{
if(empty($this->Get_Note_Header_By_ID_Num($ID_Num)['Date']) && empty($this->Get_Note_Header_By_ID_Num($ID_Num)['Size']) && empty($this->Get_Note_Header_By_ID_Num($ID_Num)['Msgno']))
return FALSE;
else
return TRUE;
}
/**
* Check if the a note is currently marked as deleted (based on note ID).
*
* @param int $ID_Num The numerical ID of the note.
*
* @return boolean <u>Description:</u><br>TRUE if the note is marked as deleted. FALSE if the note is NOT marked as deleted.
*/
function Check_If_Note_Is_Deleted_By_ID_Num($ID_Num)
{
if($this->Get_Note_Header_By_ID_Num($ID_Num)['Deleted'] == "D")
return TRUE;
else
return FALSE;
}
/**
* Gets all deleted notes and returns them in an associative array.
*
* @return Array <u>Description:</u><br>Returns an associative array of deleted notes formatted as:<br>Note_ID_Number => Array(Note & Header Data)
*/
function Get_All_Deleted_Notes()
{
if (isset($this->deleted_notes))
return $this->deleted_notes;
$this->deleted_notes = Array();
for ($notenum_loop = 1; $notenum_loop <= $this->Get_Total_Notes_Count(); $notenum_loop++) {
if ($this->Get_Note_Header_By_ID_Num($notenum_loop)['Deleted'] == "D") {
array_push($this->deleted_notes, $this->Get_Note_With_Header_Data_By_ID_Num($notenum_loop));
}
}
return $this->deleted_notes;
}
/**
* Gets all regular notes and returns them in an associative array.
*
* @return Array <u>Description:</u><br>Returns an associative array of regular notes formatted as:<br>Note_ID_Number => Array(Note & Header Data)
*/
function Get_All_Regular_Notes()
{
if (isset($this->regular_notes))
return $this->regular_notes;
$this->regular_notes = Array();
for ($notenum_loop = 1; $notenum_loop <= $this->Get_Total_Notes_Count(); $notenum_loop++) {
if ($this->Get_Note_Header_By_ID_Num($notenum_loop)['Deleted'] != "D") {
array_push($this->regular_notes, $this->Get_Note_With_Header_Data_By_ID_Num($notenum_loop));
}
}
return $this->regular_notes;
}
/**
* Create a new note with a given subject and body text.
*
* @param string $Note_Subject The note subject.
* @param string $Note_Text The note body text.
*
* @return boolean <u>Description:</u><br>Returns TRUE if the note was created successfully and FALSE if the creation failed
*/
function Create_New_Note($Note_Subject, $Note_Text)
{
$currenttime = strftime('%a, %d %b %Y %H:%M:%S %z');
$note = "Date: $currenttime\nFrom: $this->email\nX-Uniform-Type-Identifier: com.apple.mail-note\nContent-Type: text/html;\nSubject: $Note_Subject\n\n$Note_Text";
return imap_append($this->imap, "{imap.mail.me.com:993/imap/ssl}Notes", $note);
}
/**
* Delete a note by ID. (And force deletion)
*
* @param int $ID_Num The note's ID number.
* @param boolean $Expunge Whether to expunge the note or not. Default is TRUE. See description.
*
* @return void <u>Description:</u><br>This method deletes a note by ID. If $Expunge is set to FALSE it will only mark the message for deletion (set a flag). Setting it to TRUE forces deletion of the message. This may also delete all other messages that have been marked for deletion.
*/
function Delete_Note_By_ID($ID_Num, $Expunge = TRUE)
{
imap_delete($this->imap,$ID_Num);
if($Expunge)
imap_expunge($this->imap);
}
/**
* UnDelete a note by ID (that has been marked as deleted)
*
* @param int $ID_Num The note's ID number.
*
* @return void <u>Description:</u><br>This method deletes a note by ID. It is designed to undelete notes that are marked as deleted but are still in the icloud.<u>Warning:</u><br> Setting $Expunge to TRUE will destroy any chance of recovering accidentally deleted notes.
*/
function UnDelete_Note_By_ID($ID_Num)
{
imap_undelete($this->imap, $ID_Num);
}
/**
* Permenantly deletes all notes that are marked as "deleted" but are still in the icloud.
*
*
* @return void <u>Warning:</u><br> This will destroy any chance of recovering accidentally deleted notes.
*/
function Expunge_Notes_Pending_Deletion()
{
imap_expunge($this->imap);
}
/**
* Searches all regular notes (note body text) for a given string. Supports case sensitivity and regex.
*
* @param string $search_string The string to search for. (or the pattern to match if in regex mode)
* @param int $search_mode The search mode. 0 for RegEx, 1 for CaSe SeNsItIvE, 2 for case insensitive.
*
* @return Array <u>Description:</u><br>Returns an associative array of regular notes that matched the search string or pattern formatted as:<br>Note_ID_Number => Array(Note & Header Data)
*/
function Search_Notes($search_string, $search_mode)
{
$matches = Array();
foreach ($this->Get_All_Regular_Notes() as $regnote)
{
switch($search_mode)
{
//ReGex search
case 0:
if(preg_match("/".$search_string."/",$regnote['Note']) > 0)
$matches = $matches + $regnote;
break;
//CaSe SeNsItIvE search
case 1:
if(strstr($regnote['Note'],$search_string) != FALSE)
$matches = $matches + $regnote;
break;
//case insensitive search
case 2:
if(stristr($regnote['Note'],$search_string) != FALSE)
$matches = $matches + $regnote;
break;
default:
die("Error: Invalid Search Mode given in function Search_Notes()");
}
}
return $matches;
}
/**
* Generate a list of note IDs in Ascending order (from oldest to newest note based on note timestamps).
*
* @return Array <u>Description:</u><br> Returns an array of note ID's with the oldest note ID in slot O of the array, and the newest note ID in the last slot of the array.
*/
function List_Note_IDs_By_Date_Ascending()
{
$Sorted_IDs = Array();
foreach($this->Get_All_Regular_Notes() as $Note_ID => $Note_Data_Array)
{
$Sorted_IDs = $Sorted_IDs + Array($Note_ID+1 => $Note_Data_Array['Unix-Date']);
}
asort($Sorted_IDs);
return array_keys($Sorted_IDs);
}
//newest to oldest
/**
* Generate a list of note IDs in Descending order (from newest to oldest note based on note timestamps).
*
* @return Array <u>Description:</u><br> Returns an array of note ID's with the newest note ID in slot O of the array, and the oldest note ID in the last slot of the array.
*/
function List_Note_IDs_By_Date_Descending()
{
$Sorted_IDs = Array();
foreach($this->Get_All_Regular_Notes() as $Note_ID => $Note_Data_Array)
{
$Sorted_IDs = $Sorted_IDs + Array($Note_ID+1 => $Note_Data_Array['Unix-Date']);
}
arsort($Sorted_IDs);
return array_keys($Sorted_IDs);
}
}