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