1<?php 2 /**************************************************************************\ 3 * AngleMail - E-Mail Message Processing Functions * 4 * http://www.anglemail.org * 5 * http://www.phpgroupware.org * 6 */ 7 /**************************************************************************\ 8 * AngleMail - E-Mail Message Processing Functions * 9 * This file written by Angelo Puglisi (Angles) <angles@aminvestments.com> * 10 * Handles specific operations in manipulating email messages * 11 * Copyright (C) 2001, 2002 Angelo Tony Puglisi (Angles) * 12 * ------------------------------------------------------------------------ * 13 * This library is free software; you can redistribute it and/or modify it * 14 * under the terms of the GNU Lesser General Public License as published by * 15 * the Free Software Foundation; either version 2.1 of the License, * 16 * or any later version. * 17 * This library is distributed in the hope that it will be useful, but * 18 * WITHOUT ANY WARRANTY; without even the implied warranty of * 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 20 * See the GNU Lesser General Public License for more details. * 21 * You should have received a copy of the GNU Lesser General Public License * 22 * along with this library; if not, write to the Free Software Foundation, * 23 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 24 \**************************************************************************/ 25 26 /* $Id: class.mail_msg_wrappers.inc.php 15464 2004-11-06 16:13:49Z powerstat $ */ 27 28 // ===== INTERFACE FUNCTIONS AND/OR WRAPPER FUNCTIONS ===== 29 30 /*! 31 @class mail_msg_wrappers 32 @abstract Wrapper functions to be called as "public" functions 33 @discussion Hides the implementation details from the calling process 34 Provides most args to the dcom class from variables which class msg processed and set 35 Sometimes returns processed data ready to be used for display or information 36 MORE DISCUSSION - Why Wrap Here? 37 Answer: because once the msg class opens a mailsvr_stream, that will be the only stream 38 that instance of the class will have, so WHY keep supplying it as an arg EVERY time? 39 Also, same for the "msgnum", unless you are looping thru a message list, you are 40 most likely concerned with only ONE message, and the variable would be the MIME part therein 41 */ 42 class mail_msg_wrappers extends mail_msg_base 43 { 44 45 /*! 46 @function mail_msg_wrappers 47 @abstract CONSTRUCTOR place holder, does nothing 48 */ 49 function mail_msg_wrappers() 50 { 51 return; 52 } 53 54 // ==== Functions For Getting Information About A Message ==== 55 56 /*! 57 @function phpgw_fetchstructure 58 @abstract wrapper for IMAP_FETSCSTRUCTURE, phpgw supplies the nedessary stream arg 59 @param $msgnum integer 60 @result returns the IMAP_FETSCSTRUCTURE data 61 @discussion Wrapper supplies the needed mailsvr_stream arg to IMAP_FETSCSTRUCTURE 62 The data communications object (class mail_dcom) is supplied by the class. NOTE: this data 63 CAN ONLY BE OBTAINED FOR A MSG IN THE CURRENTLY SELECTED FOLDER. 64 This means we automatically know which folder this data applies to because it can ONLY be 65 the currently selected folder, and only one folder can be selected at any one time. 66 CACHE NOTE if $this->session_cache_extreme is True, then this data is cached and 67 manipulated by the "extreme" caching code, which will pop a cached "msg_structure" out 68 of cache if the message is moved to another folder. If $this->session_cache_extreme is False, 69 then caching is NOT used on this data. 70 */ 71 function phpgw_fetchstructure($msgball='') 72 { 73 if (!(isset($msgball)) 74 || ((string)$msgball == '')) 75 { 76 $msgball = $this->get_arg_value('msgball'); 77 } 78 $acctnum = $msgball['acctnum']; 79 if (!(isset($acctnum)) 80 || ((string)$acctnum == '')) 81 { 82 $acctnum = $this->get_acctnum(); 83 } 84 85 // CHECK FOR CACHED ITEM 86 // if "session_cache_extreme" is not enabled, do not use caching for this data 87 88 if ($this->session_cache_extreme == True) 89 { 90 // function read_session_cache_item($data_name='misc', $acctnum='', $extra_keys='') 91 // this key, if it exists in the cached array of msg_structures, will hold the data we want as its value 92 // this msgball *may* not have a "folder" element because fetchstructure can only be for the current folder anyway 93 // so sometimes we feed the msgball with no folder into here because it is obvious anyway. 94 if ((isset($msgball['folder'])) 95 && (trim($msgball['folder']) != '')) 96 { 97 //$extra_keys = $msgball['folder'].'_'.(string)$msgball['msgnum']; 98 $ex_folder = $msgball['folder']; 99 $ex_msgnum = $msgball['msgnum']; 100 } 101 else 102 { 103 //$extra_keys = $this->prep_folder_out().'_'.(string)$msgball['msgnum']; 104 $ex_folder = $this->prep_folder_out(); 105 $ex_msgnum = $msgball['msgnum']; 106 } 107 // the cached data is returned as a ready to use object if it exists, or False if not existing 108 //$cache_msg_structure = $this->read_session_cache_item('msg_structure', $acctnum, $extra_keys); 109 $cache_msg_structure = $this->read_session_cache_item('msg_structure', $acctnum, $ex_folder, $ex_msgnum); 110 //echo '** phpgw_fetchstructure: $specific_key ['.$specific_key.'] :: $cache_msg_structure DUMP<pre>'; print_r($cache_msg_structure); echo '</pre>'; 111 } 112 else 113 { 114 // provide an empty var so the following if .. then does not complain about "undefined var" 115 // because this var is tested along with the "cache_phpgw_header" flag, it should at least 116 // exist even if caching is not turned on just so the following test is "cool" with it 117 $cache_msg_structure = ''; 118 } 119 120 if (($cache_msg_structure) 121 && ($this->session_cache_extreme == True)) 122 { 123 //echo '** phpgw_fetchstructure: $specific_key ['.$specific_key.'] :: $cache_msg_structure DUMP<pre>'; print_r($cache_msg_structure); echo '</pre>'; 124 return $cache_msg_structure; 125 } 126 else 127 { 128 // NO CACHED ITEM or CACHING NOT ENABLED 129 // get the data from the mail server 130 $this->ensure_stream_and_folder($msgball, 'phpgw_fetchstructure'.' LINE '.__LINE__); 131 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 132 $data = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->fetchstructure($mailsvr_stream, $msgball['msgnum']); 133 // PUT THIS IN CACHE 134 // if "session_cache_extreme" is True 135 if ($this->session_cache_extreme == True) 136 { 137 // this msgball *may* not have a "folder" element because fetchstructure can only be for the current folder anyway 138 // so sometimes we feed the msgball with no folder into here because it is obvious anyway. 139 // But for caching purposes we will MAKE SURE it has folder so we can check the cache for other than the selected folder 140 // at a later date 141 if (!(isset($msgball['folder'])) 142 || ($msgball['folder'] == '')) 143 { 144 //$msgball['folder'] = $this->get_arg_value('folder'); 145 $msgball['folder'] = $this->prep_folder_out($this->get_arg_value('folder')); 146 } 147 // this is the way we pass msg_structure data to the caching function 148 // NOTE that $extra_keys is generated FOR US in the function that saves this to appsesion cache 149 $meta_data = array(); 150 $meta_data['msgball'] = array(); 151 $meta_data['msgball'] = $msgball; 152 $meta_data['msg_structure'] = $data; 153 154 // SET_CACHE_ITEM 155 //echo 'saving msg_structure to cache<br />'; 156 $this->save_session_cache_item('msg_structure', $meta_data, $acctnum); 157 } 158 return $data; 159 } 160 } 161 162 /*! 163 @function phpgw_header 164 @abstract wrapper for IMAP_HEADER, phpgw supplies the necessary stream arg and mail_dcom reference 165 @param $msgball (typed array) 166 @result returns the php IMAP_HEADER data 167 @discussion Wrapper supplies the needed mailsvr_stream arg to IMAP_HEADER. 168 Message Information: THE MESSAGE'S HEADERS RETURNED AS A STRUCTURE. 169 The data communications object (class mail_dcom) is supplied by the class. 170 CACHE NOTE if $this->session_cache_extreme is True, then this data is cached and 171 manipulated by the "extreme" caching code, which will pop a cached "phpgw_header" out 172 of cache if the message is moved to another folder, and manually clear a cached "phpgw_header" 173 items flag from "unseen" or "recent", if necessary, if the message is read, and put the updated 174 "phpgw_header" item back in cache, with no need to contact the mailserver about this. Eventhough 175 we still need to contact the mail server to get the body, by manually clearing the flag, if necssary, as 176 described above, then when the user goes back to the message list after reading the message, 177 it is possible that ALL information required to make that index page is "fresh" in local cache, 178 and NO login to the mailserver is done in that case. Situations where ALL the necessary data 179 is not in the cache are as follows, if the user deleted or moved ONE message, for example, it 180 may be possible that the index page needs to contact the mailserver to get one additional "phpgw_header" 181 (and also one additional "msg_structure") item to fill out the message list page. If the user had already 182 viewed the index page that had that message, such as paging forward and then backwards thru the 183 message list, the the single message that *was* on the next message list page that is now on the *current* 184 message list page, would already be in the cache. If $this->session_cache_extreme is False, 185 then caching is NOT used on this data. 186 */ 187 function phpgw_header($msgball='') 188 { 189 if (!(isset($msgball)) 190 || ((string)$msgball == '')) 191 { 192 $msgball = $this->get_arg_value('msgball'); 193 } 194 //$acctnum = $msgball['acctnum']; 195 //if (!(isset($acctnum)) 196 //|| ((string)$acctnum == '')) 197 //{ 198 // $acctnum = $this->get_acctnum(); 199 //} 200 if ((isset($msgball['acctnum'])) 201 || ((string)$msgball['acctnum'] != '')) 202 { 203 $acctnum = $msgball['acctnum']; 204 } 205 else 206 { 207 $acctnum = $this->get_acctnum(); 208 $msgball['acctnum'] = $acctnum; 209 } 210 211 // CHECK FOR CACHED ITEM 212 // if "session_cache_extreme" is not enabled, do not use caching for this data 213 214 if ($this->session_cache_extreme == True) 215 { 216 // function read_session_cache_item($data_name='misc', $acctnum='', $extra_keys='') 217 // this key, if it exists in the cached array of msg_structures, will hold the data we want as its value 218 // this msgball *may* not have a "folder" element because header can only be for the current folder anyway 219 // so sometimes we feed the msgball with no folder into here because it is obvious anyway. 220 if ((isset($msgball['folder'])) 221 && (trim($msgball['folder']) != '')) 222 { 223 //$extra_keys = $msgball['folder'].'_'.(string)$msgball['msgnum']; 224 $ex_folder = $msgball['folder']; 225 $ex_msgnum = $msgball['msgnum']; 226 } 227 else 228 { 229 //$extra_keys = $this->prep_folder_out().'_'.(string)$msgball['msgnum']; 230 $ex_folder = $this->prep_folder_out(); 231 $ex_msgnum = $msgball['msgnum']; 232 } 233 // the cached data is returned as a ready to use object if it exists, or False if not existing 234 //$cache_phpgw_header = $this->read_session_cache_item('phpgw_header', $acctnum, $extra_keys); 235 $cache_phpgw_header = $this->read_session_cache_item('phpgw_header', $acctnum, $ex_folder, $ex_msgnum); 236 //echo '** phpgw_header: $specific_key ['.$specific_key.'] :: $cache_phpgw_header DUMP<pre>'; print_r($cache_phpgw_header); echo '</pre>'; 237 } 238 else 239 { 240 // provide an empty var so the following if .. then does not complain about "undefined var" 241 // because this var is tested along with the "cache_phpgw_header" flag, it should at least 242 // exist even if caching is not turned on just so the following test is "cool" with it 243 $cache_phpgw_header = ''; 244 } 245 246 if (($cache_phpgw_header) 247 && ($this->session_cache_extreme == True)) 248 { 249 //echo '** phpgw_header: $specific_key ['.$specific_key.'] :: $cache_phpgw_header DUMP<pre>'; print_r($cache_phpgw_header); echo '</pre>'; 250 return $cache_phpgw_header; 251 } 252 else 253 { 254 // NO CACHED ITEM or CACHING NOT ENABLED 255 // get the data from the mail server 256 $this->ensure_stream_and_folder($msgball, 'phpgw_header'.' LINE '.__LINE__); 257 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 258 $data = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->header($mailsvr_stream, $msgball['msgnum']); 259 260 // fix escape problem FORGET THIS FOR NOW 261 //$this->cache_clean_phpgw_header($data); 262 263 // PUT THIS IN CACHE 264 // if "session_cache_extreme" is True 265 if (($data) 266 && ($this->session_cache_extreme == True)) 267 { 268 // this msgball *may* not have a "folder" element because header can only be for the current folder anyway 269 // so sometimes we feed the msgball with no folder into here because it is obvious anyway. 270 // But for caching purposes we will MAKE SURE it has folder so we can check the cache for other than the selected folder 271 // at a later date 272 if (!(isset($msgball['folder'])) 273 || ($msgball['folder'] == '')) 274 { 275 //$msgball['folder'] = $this->get_arg_value('folder'); 276 $msgball['folder'] = $this->prep_folder_out($this->get_arg_value('folder')); 277 } 278 279 // fix escape problem 280 //$this->cache_clean_phpgw_header($data); 281 282 // this is the way we pass phpgw_header data to the caching function 283 $meta_data = array(); 284 $meta_data['msgball'] = array(); 285 $meta_data['msgball'] = $msgball; 286 $meta_data['phpgw_header'] = $data; 287 288 // SET_CACHE_ITEM 289 // NOTE that $extra_keys is generated FOR US in the function that saves this to appsesion cache 290 //echo 'saving phpgw_header to cache<br />'; 291 $this->save_session_cache_item('phpgw_header', $meta_data, $acctnum); 292 } 293 if (!$data) 294 { 295 return False; 296 } 297 else 298 { 299 return $data; 300 } 301 } 302 } 303 304 /*! 305 @function cache_clean_phpgw_header 306 @abstract ? 307 @param $msg_headers (php struct from header) btw it is a refrence OOP directly on param 308 @author Angles 309 @discussion ? 310 311 function cache_clean_phpgw_header(&$msg_headers) 312 { 313 //$debug = 0; 314 $debug = 3; 315 316 if ( 317 (!isset($msg_headers)) 318 || (!$msg_headers ) 319 //|| ($this->session_cache_extreme == False) 320 ) 321 { 322 return ''; 323 } 324 // toaddress 325 // to[] 326 // fromaddress 327 // from[] 328 // reply_toaddress 329 // reply_to[] 330 // senderaddress 331 // sender[] 332 // cc[] 333 334 if ($debug > 2) { $this->dbug->out('wrappers.cache_clean_phpgw_header('.__LINE__.'): BEFORE $msg_headers DUMP:', $msg_headers); } 335 // toaddress 336 if ($msg_headers->toaddress) 337 { 338 $msg_headers->toaddress = addslashes($msg_headers->toaddress); 339 } 340 341 // to[] 342 if ($msg_headers->to) 343 { 344 $loops = count($msg_headers->to); 345 for($i=0;$i<$loops;$i++) 346 { 347 $thingy =& $msg_headers->to[$i]; 348 $thingy->personal = addslashes($thingy->personal); 349 } 350 } 351 // fromaddress 352 if ($msg_headers->fromaddress) 353 { 354 $msg_headers->fromaddress = addslashes($msg_headers->fromaddress); 355 } 356 // from[] 357 if ($msg_headers->from) 358 { 359 $loops = count($msg_headers->from); 360 for($i=0;$i<$loops;$i++) 361 { 362 $thingy =& $msg_headers->from[$i]; 363 $thingy->personal = addslashes($thingy->personal); 364 } 365 } 366 367 // reply_toaddress 368 if ($msg_headers->reply_toaddress) 369 { 370 $msg_headers->reply_toaddress = addslashes($msg_headers->reply_toaddress); 371 } 372 // reply_to[] 373 if ($msg_headers->reply_to) 374 { 375 $loops = count($msg_headers->reply_to); 376 for($i=0;$i<$loops;$i++) 377 { 378 $thingy =& $msg_headers->reply_to[$i]; 379 $thingy->personal = addslashes($thingy->personal); 380 } 381 } 382 383 // senderaddress 384 if ($msg_headers->senderaddress) 385 { 386 $msg_headers->senderaddress = addslashes($msg_headers->senderaddress); 387 } 388 // sender[] 389 if ($msg_headers->sender) 390 { 391 $loops = count($msg_headers->sender); 392 for($i=0;$i<$loops;$i++) 393 { 394 $thingy =& $msg_headers->sender[$i]; 395 $thingy->personal = addslashes($thingy->personal); 396 } 397 } 398 399 // cc[] 400 401 if ($debug > 2) { $this->dbug->out('wrappers.cache_clean_phpgw_header('.__LINE__.'): AFTER $msg_headers DUMP:', $msg_headers); } 402 } 403 */ 404 405 /*! 406 @function phpgw_fetchheader 407 @abstract returns the message RAW headers as a blob, or long string. 408 @param $msgball (typed array) 409 @author Angles 410 @discussion Used by filtering, and in other cases where testing or checking the 411 actual message headers as a text item, is necessary. 412 */ 413 function phpgw_fetchheader($msgball='') 414 { 415 if (!(isset($msgball)) 416 || ((string)$msgball == '')) 417 { 418 $msgball = $this->get_arg_value('msgball'); 419 } 420 $acctnum = $msgball['acctnum']; 421 if (!(isset($acctnum)) 422 || ((string)$acctnum == '')) 423 { 424 $acctnum = $this->get_acctnum(); 425 } 426 427 $this->ensure_stream_and_folder($msgball, 'phpgw_fetchheader'.' LINE '.__LINE__); 428 429 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 430 // Message Information: THE MESSAGE'S HEADERS RETURNED RAW (no processing) 431 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->fetchheader($mailsvr_stream, $msgball['msgnum']); 432 } 433 434 /*! 435 @function all_headers_in_folder 436 @abstract wrapper for IMAP_HEADERS, phpgw supplies the nedessary stream arg and mail_dcom reference 437 @param $fldball array[folder] string ; array[acctnum] int 438 @result returns the php IMAP_HEADERS data, php manual says 439 function.imap-headers.php 440 Returns headers for all messages in a mailbox 441 Returns an array of string formatted with header info. One element per mail message 442 @discussion = = = = USELESS FUNCTION = = = = 443 returns array of strings, each string is extremely truncated 444 partial contents of date, from, and subject, also includes the msg size in chars 445 */ 446 function all_headers_in_folder($fldball='') 447 { 448 if (!(isset($fldball)) 449 || ((string)$fldball == '')) 450 { 451 $msgball = $this->get_arg_value('fldball'); 452 } 453 $acctnum = $fldball['acctnum']; 454 if (!(isset($acctnum)) 455 || ((string)$acctnum == '')) 456 { 457 $acctnum = $this->get_acctnum(); 458 } 459 $this->ensure_stream_and_folder($fldball, 'all_headers_in_folder'); 460 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 461 462 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->headers($mailsvr_stream); 463 } 464 465 /*! 466 @function phpgw_get_flag 467 @abstract ? 468 */ 469 function phpgw_get_flag($flag='') 470 { 471 // sanity check 472 if ($flag == '') 473 { 474 return ''; 475 } 476 else 477 { 478 $msgball = $this->get_arg_value('msgball'); 479 $this->ensure_stream_and_folder($msgball , 'phpgw_get_flag'.' LINE '.__LINE__); 480 return $GLOBALS['phpgw_dcom_'.$this->acctnum]->dcom->get_flag($this->get_arg_value('mailsvr_stream'),$this->get_arg_value('["msgball"]["msgnum"]'),$flag); 481 } 482 } 483 484 // ==== Functions For Getting A Message Or A Part (MIME Part) Of A Message ==== 485 486 /*! 487 @function phpgw_body 488 @abstract get the entire body for a message. 489 @param $msgball (typed array) 490 @author Angles 491 @discussion If only a part of the message body is desired, use "phpgw_fetchbody" instead. 492 */ 493 function phpgw_body($msgball='') 494 { 495 if (!(isset($msgball)) 496 || ((string)$msgball == '')) 497 { 498 $msgball = $this->get_arg_value('msgball'); 499 } 500 $acctnum = $msgball['acctnum']; 501 if (!(isset($acctnum)) 502 || ((string)$acctnum == '')) 503 { 504 $acctnum = $this->get_acctnum(); 505 } 506 $this->ensure_stream_and_folder($msgball, 'phpgw_body'.' LINE '.__LINE__); 507 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 508 // notice of event 509 $this->event_msg_seen($msgball, 'phpgw_body'); 510 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->get_body($mailsvr_stream, $msgball['msgnum']); 511 } 512 513 /*! 514 @function phpgw_fetchbody 515 @abstract FETCHBODY get a portion, via MIME part number, of a message body, not the entire body. 516 @param $msgball (typed array) 517 @param $flags (defined int) options passed to the mailserver with the php FETCHBODY command. 518 (Not related to a message flag like "unseen", this is an optional argument for the mail server.) 519 @author Angles 520 */ 521 function phpgw_fetchbody($msgball='', $flags='') 522 { 523 //echo 'mail_msg(_wrappers): phpgw_fetchbody: ENTERING, $msgball dump<pre>'; print_r($msgball); echo '</pre>'; 524 if ( (!isset($msgball)) 525 || ($msgball == '') ) 526 { 527 $msgball = $this->get_arg_value('msgball'); 528 } 529 $acctnum = $msgball['acctnum']; 530 // why is this next check needed? 531 if ((!isset($acctnum)) 532 || ((string)$acctnum == '')) 533 { 534 $acctnum = $this->get_acctnum(); 535 } 536 537 // TRY CACHED DATA 538 $cached_phpgw_fetchbody = $this->read_session_cache_item('phpgw_fetchbody', $msgball['acctnum'], $msgball['folder'], $msgball['msgnum'], $msgball['part_no']); 539 if ($cached_phpgw_fetchbody) 540 { 541 // notice of event 542 $this->event_msg_seen($msgball, 'phpgw_fetchbody'); 543 return $cached_phpgw_fetchbody; 544 } 545 // if we get here we need to contact mailserver 546 $this->ensure_stream_and_folder($msgball, 'phpgw_fetchbody'.' LINE '.__LINE__); 547 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 548 $msgnum = $msgball['msgnum']; 549 $part_no = $msgball['part_no']; 550 //echo 'mail_msg(_wrappers): phpgw_fetchbody: processed: $acctnum: '.$acctnum.'; $mailsvr_stream: '.serialize($mailsvr_stream).'; $msgnum: '.$msgnum.'; $part_no: '.$part_no.'<br /> * $msgball dump<pre>'; print_r($msgball); echo '</pre>'; 551 552 $data = ''; 553 $data = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->fetchbody($mailsvr_stream, $msgnum, $part_no, $flags); 554 555 if ($data) 556 { 557 // notice of event 558 $this->event_msg_seen($msgball, 'phpgw_fetchbody'); 559 // SET_CACHE_ITEM 560 $meta_data = array(); 561 $meta_data['msgball'] = $msgball; 562 $meta_data['phpgw_fetchbody'] = $data; 563 $this->save_session_cache_item('phpgw_fetchbody', $meta_data, $acctnum); 564 $meta_data = array(); 565 return $data; 566 } 567 else 568 { 569 return False; 570 } 571 } 572 573 /* 574 // OLD FUNCTION 575 function phpgw_fetchbody($msgball='', $flags='') 576 { 577 //echo 'mail_msg(_wrappers): phpgw_fetchbody: ENTERING, $msgball dump<pre>'; print_r($msgball); echo '</pre>'; 578 if ( (!isset($msgball)) 579 || ($msgball == '') ) 580 { 581 $msgball = $this->get_arg_value('msgball'); 582 } 583 $acctnum = $msgball['acctnum']; 584 if ((!isset($acctnum)) 585 || ((string)$acctnum == '')) 586 { 587 $acctnum = $this->get_acctnum(); 588 } 589 $this->ensure_stream_and_folder($msgball, 'phpgw_fetchbody'.' LINE '.__LINE__); 590 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 591 $msgnum = $msgball['msgnum']; 592 $part_no = $msgball['part_no']; 593 //echo 'mail_msg(_wrappers): phpgw_fetchbody: processed: $acctnum: '.$acctnum.'; $mailsvr_stream: '.serialize($mailsvr_stream).'; $msgnum: '.$msgnum.'; $part_no: '.$part_no.'<br /> * $msgball dump<pre>'; print_r($msgball); echo '</pre>'; 594 595 // notice of event 596 $this->event_msg_seen($msgball, 'phpgw_fetchbody'); 597 598 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->fetchbody($mailsvr_stream, $msgnum, $part_no, $flags); 599 } 600 */ 601 602 // ===== Functions For Getting Information About A Folder ===== 603 // returns an array of integers which are refer to all the messages in a folder ("INBOX") sorted and ordered 604 // any integer in this array can be used to request that specific message from the server 605 /*! 606 @function get_msgball_list 607 @abstract wrapper for IMAP_SORT, sorts a folder in the desired way, then get a list of all message, as integer message numbers 608 @param $acctnum int SPECIAL USE ONLY you may supply an acctnum to get info about a folder the is not the currently selected acct / folder 609 @param $folder string SPECIAL USE ONLY you may supply folder name to get info about a folder the is not the currently selected acct / folder 610 @param $only_fill_cache (boolean) SPECIAL USE ONLY when we only want to make sure the cache has data, so we can reference 611 it after we call this function, so we do not actually want data returned here (EXPERIMENTAL, MAY NOT WORK) 612 @author Angles 613 @access public 614 @result returns an array of of type "msgball" , so it contains acctnum, foldername, message UID, and some other info, such as a 615 pre-prepared "fake URI" a.k.a. a GET URI string of type magball. Important data is the message UID integers which 616 are message numbers referring to messages in the current folder. Because multiple accounts may be in use, the msgball array 617 structure is necessary so the correct acctnum and foldername accompanies each message UID. Therefor you have enough information 618 to take all sorts of action on any particular message in the list, see discussion below. 619 @discussion Folder and Account Number SHOULD be obtained from the class vars which were set during begin_request(), 620 where folder and acctnum were determined from GET POST data or data supplied to begin_request() in its arg array. This way 621 the desired folder is known to be correctly named (it exists, not a bogus foldername) and associated with the correct acctnum. 622 However, some of the filter functions do use these params, but using them is discouraged. 623 The return is an array of "msgball" data, which contains acctnum, foldername, message UID, and some other info, such as a 624 pre-prepared "fake URI" a.k.a. a GET URI string of type magball. Use this data and specifically these message numbers 625 to request more detailed information about a message (headers, subject), or the request message itself from the server. 626 Sort and Order is applied by the class, so the calling process does not need to specify sorting here 627 The data communications object (class mail_dcom) is supplied by the class 628 */ 629 function get_msgball_list($acctnum='', $folder='', $only_fill_cache=False) 630 { 631 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(wrappers).get_msgball_list: ENTERING $acctnum ['.$acctnum.'] ; $folder ['.$folder.'] <br />'); } 632 // IF specifying a folder, as a filter search may do, we need to ensure stream and folder 633 if ((isset($acctnum)) 634 && ((string)$acctnum != '') 635 && (isset($folder)) 636 && ((string)$folder != '')) 637 { 638 // SPECIAL HANDLING, typical message viewing would not need to specify folder 639 // DO NOT SPECIFY FOLDER unless you *really* know what you are doing 640 // typically "best" folder and acctnum are obtained during begin request 641 // right now only specialized filter searching requires tp specify a folder 642 643 // UPDATE WE NOW USE A FOLDER ARG IN THE DATA KEY 644 // not sure how that changes any of this, if at all 645 // in this case, not even an acctnum was passed, so obviously a folder is out of the question here 646 647 $fake_fldball = array(); 648 $fake_fldball['acctnum'] = $acctnum; 649 $fake_fldball['folder'] = $folder; 650 // WHY DO THIS HERE? 651 //$this->ensure_stream_and_folder($fake_fldball, 'get_msgball_list'.' LINE '.__LINE__); 652 // ok, so now we KNOW the stream exists and folder value is what we need for this desired account 653 } 654 elseif ((!isset($acctnum)) 655 || ((string)$acctnum == '')) 656 { 657 $acctnum = $this->get_acctnum(); 658 } 659 // as I said above, rare to specify folder, if it wasn;t handled above, forget about it 660 661 // try to restore "msgball_list" from saved session data store 662 // in appsession this data is saved like this: 663 // $cached_msgball_data[msgball_list] 664 // $cached_msgball_data[validity] 665 // BUT IT RETURNS TO US THE ACTUAL "msgball_list" part, *NOT* WITH THE OTHER STUFF TOO 666 //$cached_msgball_list = $this->read_session_cache_item('msgball_list', $acctnum); 667 // NOW WE USE FOLDER NAME AS A DATA KEY TOO 668 if ((!isset($folder)) 669 || ((string)$folder == '')) 670 { 671 $folder = $this->prep_folder_out($this->get_arg_value('folder', $acctnum)); 672 } 673 $cached_msgball_list = $this->read_session_cache_item('msgball_list', $acctnum, $folder); 674 if ($cached_msgball_list) 675 { 676 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(wrappers).get_msgball_list: ('.__LINE__.') LEAVING, returning appsession cached "msgball_list"<br />'); } 677 // 678 //return $cached_msgball_data['msgball_list']; 679 return $cached_msgball_list; 680 } 681 else 682 { 683 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(wrappers).get_msgball_list: ('.__LINE__.') <font color="brown">cached had NO DATA for "msgball_list"</font><br />'); } 684 // right now only specialized filter searching requires tp specify a folder 685 $fake_fldball = array(); 686 $fake_fldball['acctnum'] = $acctnum; 687 //$fake_fldball['folder'] = $this->get_arg_value('folder'); 688 $fake_fldball['folder'] = $this->prep_folder_out($this->get_arg_value('folder')); 689 $this->ensure_stream_and_folder($fake_fldball, 'get_msgball_list'.' LINE '.__LINE__); 690 691 $server_msgnum_list = array(); 692 693 //if (is_object($GLOBALS['phpgw_dcom_'.$acctnum])) 694 //{ 695 // $server_msgnum_list = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->sort($this->get_arg_value('mailsvr_stream', $acctnum), $this->get_arg_value('sort', $acctnum), $this->get_arg_value('order', $acctnum)); 696 //} 697 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): get_msgball_list: ('.__LINE__.') <font color="red">MAILSERVER CALL</font> calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->sort('.$this->get_arg_value('mailsvr_stream', $acctnum).', '.$this->get_arg_value('sort', $acctnum).', '.$this->get_arg_value('order', $acctnum).')<br />'); } 698 $server_msgnum_list = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->sort($this->get_arg_value('mailsvr_stream', $acctnum), $this->get_arg_value('sort', $acctnum), $this->get_arg_value('order', $acctnum)); 699 700 // put more information about these particular messages into the msgball_list[] structure 701 /* 702 $msgball_list = array(); 703 $loops = count($server_msgnum_list); 704 // folder empty (or an error?), msg_nums_list[] count will be 0, so msgball_list[] will be empty as well 705 // because we'll never fill it with anything 706 if ($loops > 0) 707 { 708 // we store folder in URLENCODED form in the msgball and therefor the msgball_list 709 $msg_folder = $this->prep_folder_out($this->get_arg_value('folder', $acctnum)); 710 for($i=0;$i<$loops;$i++) 711 { 712 $msgball_list[$i]['msgnum'] = $server_msgnum_list[$i]; 713 $msgball_list[$i]['folder'] = $msg_folder; 714 $msgball_list[$i]['acctnum'] = $acctnum; 715 // see php manual page "function.parse-str.html" for explanation of the array'ing of the URI data 716 // NOTE: this uri NEVER begins with a "&" here 717 // YOU must add the prefix "&" if it's needed 718 $msgball_list[$i]['uri'] = 719 'msgball[msgnum]='.$msgball_list[$i]['msgnum'] 720 .'&msgball[folder]='.$msgball_list[$i]['folder'] 721 .'&msgball[acctnum]='.$msgball_list[$i]['acctnum']; 722 // NEW - try making the msgball_list URI DATA ONLY 723 $msgball_list_uri_only[$i] = $msgball_list[$i]['uri']; 724 } 725 } 726 */ 727 $msgball_list = array(); 728 $loops = count($server_msgnum_list); 729 // folder empty (or an error?), msg_nums_list[] count will be 0, so msgball_list[] will be empty as well 730 // because we'll never fill it with anything 731 if ($loops > 0) 732 { 733 // we store folder in URLENCODED form in the msgball and therefor the msgball_list 734 $msg_folder = $this->prep_folder_out($this->get_arg_value('folder', $acctnum)); 735 for($i=0;$i<$loops;$i++) 736 { 737 // NEW - try making the msgball_list URI DATA ONLY 738 // see php manual page "function.parse-str.html" for explanation of the array'ing of the URI data 739 // NOTE: this uri NEVER begins with a "&" here 740 // YOU must add the prefix "&" if it's needed 741 $msgball_list[$i] = 742 'msgball[msgnum]='.$server_msgnum_list[$i] 743 .'&msgball[folder]='.$msg_folder 744 .'&msgball[acctnum]='.$acctnum; 745 } 746 } 747 748 // save "msgball_list" to session data store 749 // prepare the data for storage, save it with info to aid in "freshness" testing on later reading of the cache 750 // NOTE right now we do not use the $extra_keys param for this msgball_list data caching 751 $meta_data = array(); 752 $meta_data['msgball_list'] = $msgball_list; 753 $meta_data['validity'] = array(); 754 $meta_data['validity']['fldball'] = $fake_fldball; 755 //$this->save_session_cache_item('msgball_list', $meta_data, $acctnum); 756 // NOW WE USE FOLDER NAME ALSO IN THE DATA KEY 757 // use the folder name that was fed as a param, since this most likely represents a good key to use 758 // just in case the msgball_list, in the future, is a virtual one composed of msg from many folders 759 $this->save_session_cache_item('msgball_list', $meta_data, $acctnum, $folder); 760 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): get_msgball_list: ('.__LINE__.') LEAVING, <font color="red">had to get data from server</font><br />'); } 761 return $msgball_list; 762 } 763 } 764 765 /*! 766 @function get_msgball_list_oldschool 767 @abstract for backward compat with functions requiring a fully expanded array msgball_list instead of only URI type data. 768 @discussion The same as "get_msgball_list" EXCEPT the uri data is looped on and expanded into full array data, for 769 backwards compat with functions expected such data instead of the new style numbered list of uri string data. 770 HEAVILY DEPRECIATED. 771 @author Angles 772 @access public 773 */ 774 function get_msgball_list_oldschool($acctnum='', $folder='', $only_fill_cache=False) 775 { 776 $msgball_list = $this->get_msgball_list($acctnum, $folder, $only_fill_cache); 777 $loops = count($msgball_list); 778 for($i=0;$i<$loops;$i++) 779 { 780 // so we do not have 2 arrays around at the same time, just use the same one for this 781 $msgball_list[$i] = $this->ball_data_parse_str($msgball_list[$i]); 782 } 783 return $msgball_list; 784 } 785 786 /*! 787 @function get_folder_size 788 @abstract uses IMAP_MAILBOXMSGINFO but returns only the size element 789 @result integer returns the SIZE element of the php IMAP_MAILBOXMSGINFO data 790 @discussion used only if the total size of a folder is desired, which takes time for the server to return 791 The other data IMAP_MAILBOXMSGINFO returns (if size is NOT needed) is obtainable 792 from "get_folder_status_info" more quickly and wth less load to the IMAP server 793 The data communications object (class mail_dcom) and mailsvr_stream are supplied by the class. 794 CACHE NOTE - USE THE WRAPPER FUNCTION "report_total_foldersize_conditional" which wraps this 795 function with logic to only actually call this function if various conditional allow us to use this 796 function, since getting size data is time consuming. STREAM NOTE - this function DOES 797 require changing folders to the onr we want size data on. This may cause problems, since normal 798 status info without size data is obtained without the need to actually switch to the subject folder. 799 For example, using this in a combobox, of in a folder list, looping thru every folder getting this data 800 requires REOPENING aka switching to the desired folder, which can confuse which folder is the 801 true desired folder. Conrast to the other stats data, which can loop thru a folder list but never require 802 actually switching folders, so this keep the true subject folder in the "folder" arg because the folder 803 is never switched away from that. 804 @author Angles 805 @access public 806 */ 807 function get_folder_size() 808 { 809 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): get_folder_size: ('.__LINE__.') ENTERING<br />'); } 810 $fldball = array(); 811 $fldball['acctnum'] = $this->get_acctnum(); 812 $fldball['folder'] = $this->prep_folder_out($this->get_arg_value('folder', $fldball['acctnum'])); 813 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): get_folder_size: ('.__LINE__.') this function does not take a param, we made a fldball: ['.serialize($fldball).']<br />'); } 814 // make sure a stream is open 815 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('mail_msg(_wrappers): get_folder_size: ('.__LINE__.') call to $this->ensure_stream_and_folder(), $fldball ['.serialize($fldball).'] <br />'); } 816 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('mail_msg(_wrappers): get_folder_size: ('.__LINE__.') NOTE THIS DOES REQUIRE A CHANGE OF FOLDER to get the data, this may cause problems. <br />'); } 817 $this->ensure_stream_and_folder($fldball, 'get_folder_size'.' LINE '.__LINE__); 818 819 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): get_folder_size: ('.__LINE__.') calling $GLOBALS[phpgw_dcom_'.$this->acctnum.']->dcom->mailboxmsginfo('.$this->get_arg_value('mailsvr_stream').', '.$fldball['acctnum'].')<br />'); } 820 $mailbox_detail = $GLOBALS['phpgw_dcom_'.$fldball['acctnum']]->dcom->mailboxmsginfo($this->get_arg_value('mailsvr_stream'), $fldball['acctnum']); 821 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): get_folder_size: ('.__LINE__.') LEAVING, returning ['.(serialize($mailbox_detail)).']<br />'); } 822 return $mailbox_detail->Size; 823 } 824 825 // ALIAS for get_folder_status_info() , for backward compatibility 826 /*! 827 @function new_message_check 828 @abstract PUBLIC function to get status info for a folder, with emphesis on reporting to user about new messages 829 @param $fldball (array of type fldball) OPTIONAL the folder you want info about. LEGACY CODE exists for older code 830 which does not use array type fldball but instead passes a string only. In not provided, the currently selected folder is inspected. 831 @discussion THIS IS A PUBLIC FUNCTION, use this one instead of "get_folder_status_info" because this function has legacy 832 code for string only param and also has extra checks for the integrity of the param data, such as with external code 833 calling this function and providing incomplete information. These param data checks do not exist in "get_folder_status_info". 834 BUT THE DATA RETURNED IS THE SAME. After these extra param checks the function calls "get_folder_status_info" to do the 835 reast of the job. So see the discussion there about what gets returned. 836 THIS IS FOR BACKWARD COMPAT ONLY, has a lot of checks verifying the input param before passing handling 837 off to the real function "get_folder_status_info", if you pass a real fldball you can just use that function. If you 838 simply want status info on the inbox of the current account, then use this function with no params, it will do the 839 rest for you. 840 @author Angles 841 @access Public 842 */ 843 function new_message_check($fldball='') 844 { 845 // detect OLD param which was string only 846 if ((isset($fldball)) 847 && (is_string($fldball)) 848 && ($fldball != '')) 849 { 850 $legacy_param = $fldball; 851 $fldball = array(); 852 $fldball['folder'] = $legacy_param; 853 // legacy param ALWAYS was applicable to acct 0 only, multi-accounts did not exist then 854 $fldball['acctnum'] = 0; 855 } 856 elseif ( (!isset($fldball)) 857 || (!$fldball)) 858 { 859 // we have NO instructions on a folder nor acctnum, so make a INBOX acct 0 fldball legacy support 860 $fldball = array(); 861 $fldball['acctnum'] = 0; 862 $fldball['folder'] = 'INBOX'; 863 } 864 865 // now we know we have a fldball structure to work with, either we made or provoded as a param 866 // see if it needs anything else we did not handle yet 867 if ((!isset($fldball['acctnum'])) 868 || ((string)$fldball['acctnum'] == '')) 869 { 870 $fldball['acctnum'] = $this->get_acctnum(); 871 872 } 873 874 // we need a folder value, this code only does allow 875 // NOTE INTERNAL CODE WILL PASS ALREADY URLENCODED FOLDER NAME 876 // This legacy code and public code EXPECTS THE PARAM WILL BE UN-ENCODED 877 // DAMN that is confusing, hummmmmmm... 878 if ((isset($fldball['folder'])) 879 && (is_string($fldball['folder'])) 880 && ($fldball['folder'] != '')) 881 { 882 $fldball['folder'] = $this->prep_folder_out($fldball['folder']); 883 } 884 else 885 { 886 $fldball['folder'] = $this->prep_folder_out('INBOX'); 887 } 888 return $this->get_folder_status_info($fldball); 889 } 890 891 /*! 892 @function get_folder_status_info 893 @abstract wrapper for IMAP_STATUS, get status info for the current folder, with emphesis on reporting to user about new messages 894 @param $fldball typed array OPTIONAL as with many functions in this class, the folder you are interested in is usually the currently 895 "selected" folder, in IMAP terms, which is selected during begin_request(), in which case it is not necessary to supply this information 896 again in this param, instead this function will use the class vars about foldername and acctnum established during begin_request(). However, 897 since there are multiple accounts, and since IMAP accounts themselves can contain many folders, it is understood that you may want 898 information about a folder other than the currently selected folder, or about an account that you may want to move messges to. In these 899 cases you may supply this param of type fldball, like this: parmarray[acctnum] = 1, parmarray[folder] = "INBOX", for example. The fldball 900 array item is pretty flexible in that only the bare minumum of data is expected to be in it, as opposed to msgball which is supposed to 901 contain quite detailed information. 902 @param $force_refresh boolean DEPRECIATED - PHASED OUT - To speed email functionality, much data collected 903 from the IMAP server is cached in some capacity, in fact the RFC on IMAP strongly encourages this. This function 904 is used by many other functions and may be called sveral times during any single operation, so the return array data 905 is cached in memory and will be returned if it is available. This is desirable in many occasions, but if for some reason 906 you need to be sure the returned information is not from this cache, set this param to TRUE. 907 =UPDATE= now this data is cached in the appsession cache IF $this->session_cache_extreme is True, and 908 assumed to be fresh for X period of time, as defined in $this->timestamp_age_limit. This param is 909 NO LONGER USED buy *MAY* be reimplemented later. 910 @result returns an associative array with 5 named elements see the example 911 @example this is the return structure 912 result['is_imap'] boolean - pop3 server do not know what is "new" or not, IMAP servers do 913 result['folder_checked'] string - the folder checked, as processed by the msg class, which may have done a lookup on the folder name 914 result['alert_string'] string - lang'd string to show the user about status of new messages in this folder 915 result['number_new'] integer - for IMAP: the number "recent" and/or "unseen"messages; for POP3: the total number of messages 916 result['number_all'] integer - for IMAP and POP3: the total number messages in the folder 917 @discussion gives user friendly "alert_string" element to show the user, info is for what ever folder the msg 918 class is currently logged into, you may want to apply PHP function "number_format()" to 919 the integers after you have done any math code and befor eyou display them to the user, it adds the thousands comma. 920 CACHE NOTE: If $this->session_cache_extreme is True, the data this function gets is cached in the appsession 921 cache and is assumed to be "fresh" for X period of time, as defined in $this->timestamp_age_limit 922 (currently hardcoded at 4 minutes). Any changes to cached elements number_new and number_all (part of this functions 923 data array) during that time are manually changed by the "extreme" caching code, we do not re-fetch this data from 924 the mailserver for changes tht we can make ourselves. 925 If $this->session_cache_extreme is False, this data is NOT put in the appsession cache, instead it is stored in a class 926 variable (L1 cache) that lasts only as long as the page view. 927 MORE CACHE NOTE: The "msgball_list" cached in the appsession cache is verified for "freshness" by comparing 928 against the "number_all" element in this functions data array. If the "number_all" of the cached "msgball_list" is 929 different from the "nunber_all" from this function, the "msgball_list" is deemed "stale" and we request a new 930 msgball list from the server, which means calling the php SORT command and adding some data to that to make 931 the "msgball_list". If $this->session_cache_extreme is True, the "extreme" caching code manually updates the 932 "number_all" cached data for this function for X minutes, as defined in $this->timestamp_age_limit, and also manually 933 updates that "number_all" that is stored with the "msgball_list" data, so that, during that X period of time, 934 as defined in $this->timestamp_age_limit, the "msgball_list" is deemed "fresh" 935 because its "number_all" element matches the "number_all" element from this functions data array. 936 If $this->session_cache_extreme is False, the same "number_all" test is done, but the data from this 937 function is ALWAYS the latest data obtained from the server because if $this->session_cache_extreme is False, 938 this function ALWAYS gets fresh folder stats data at the start of every pageview, so the "msgball_list" will be deemed 939 "stale" as soon as a change occurs on the mailserver, such as when new mail arrives or when messages are moved or 940 deleted, in which case the "msgball_list" is expired and re-fetched as described above. 941 @author Angles 942 @access public 943 */ 944 function get_folder_status_info($fldball='', $force_refresh=False) 945 { 946 if (($this->debug_session_caching > 0) || ($this->debug_wrapper_dcom_calls > 0)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') ENTERING, $fldball: '.serialize($fldball).' ; $force_refresh (DEPRECIATED): '.serialize($force_refresh).' <br />'); } 947 948 // note: param $fldball WAS just folder previously, watch out for old code still passing that string instead of the fldball 949 if ( (!isset($fldball)) 950 || (!$fldball)) 951 { 952 // we have NO instructions on a folder nor acctnum, so make a blank fldball 953 $fldball = array(); 954 $fldball['acctnum'] = ''; 955 $fldball['folder'] = ''; 956 } 957 // now we know we have a fldball structure to work with, analyse it 958 if ((!isset($fldball['acctnum'])) 959 || ((string)$fldball['acctnum'] == '')) 960 { 961 $fldball['acctnum'] = $this->get_acctnum(); 962 } 963 if ((!isset($fldball['folder'])) 964 || ((string)$fldball['folder'] == '')) 965 { 966 //$fldball['folder'] = $this->get_arg_value('folder', $fldball['acctnum']); 967 // we keep this folder name in its urlencoded form until the last second, 968 // partly so we can use it as an index member in the cache, also because it is a consistant prectice to do that 969 $fldball['folder'] = $this->prep_folder_out($this->get_arg_value('folder', $fldball['acctnum'])); 970 } 971 972 if (($this->debug_session_caching > 0) || ($this->debug_wrapper_dcom_calls > 0)) { $this->dbug->out('class_msg: get_folder_status_info('.__LINE__.'): ONLY L1 CACHE OF THIS INFO IF IN NON-EXTREME MODE<br />'); } 973 974 if ($this->session_cache_extreme == False) 975 { 976 if ($this->debug_session_caching > 1) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (non-extreme mode) uses L1/class var cache, NO appsession cache used in non-extreme <br />'); } 977 // do we have cached data in L1 cache / class object var, that we can use 978 // ONLY L1 CACHE OF THIS INFO IF IN NON-EXTREME MODE 979 //$folder_status_info = $this->get_arg_value('folder_status_info', $fldball['acctnum']); 980 $folder_status_info = $this->get_arg_value('["folder_status_info"]["'.$fldball['folder'].'"]', $fldball['acctnum']); 981 //$folder_status_info = $this->get_arg_value('folder_status_info', $fldball['acctnum'], $fldball['folder']); 982 //$folder_status_info = $this->get_arg_value_ex('folder_status_info', $fldball['acctnum'], $fldball['folder']); 983 if ((!$force_refresh) 984 && ($folder_status_info) 985 && (count($folder_status_info) > 0) 986 && ($folder_status_info['folder_checked'] == $this->prep_folder_in($fldball['folder']))) 987 { 988 // this data is cached, L1 cache, temp cache, so it should still be "fresh" 989 // add this "timestamp" array element only to imitate what exists in data structure if extreme-mode were on (which it is not here). 990 $timestamp_age = (time() - $folder_status_info['timestamp']); 991 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (non-extreme mode) got L1/class var cached data, $timestamp_age ['.$timestamp_age.'] ; $folder_status_info dump:', $folder_status_info); } 992 if (($this->debug_session_caching > 0) || ($this->debug_wrapper_dcom_calls > 0)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (non-extreme mode) LEAVING '.'<font color="purple">'.'successfully returning cached L1/class data'.'</font>'.'<br />'); } 993 return $folder_status_info; 994 } 995 else 996 { 997 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (non-extreme mode) NO data found in L1/class var cached <br />'); } 998 } 999 } 1000 else 1001 { 1002 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) uses appsession cache, no L1/class var cached is used in extreme mode, param $fldball DUMP', $fldball); } 1003 // ONLY USE APPSESSION CACHE IF IN EXTREME MODE 1004 // non-extreme mose, which was handled above, does not use appsession cache for stats data, only "L1 cache" temp class var 1005 // below is for extreme-mode, which only uses appsession cache for this data, does NOT use "L1 cache" 1006 1007 // try to restore from saved session data store 1008 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) calling $this->read_session_cache_item(folder_status_info, '.serialize($fldball['acctnum']).', '.($fldball['folder']).') NOTE the folder name MUST be urlencoded as that param<br />'); } 1009 $cached_folder_status_info = $this->read_session_cache_item('folder_status_info', $fldball['acctnum'], $fldball['folder']); 1010 if (($this->debug_session_caching > 2) || ($this->debug_wrapper_dcom_calls > 2)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) $cached_folder_status_info dump:', $cached_folder_status_info); } 1011 if ($cached_folder_status_info) 1012 { 1013 if (($this->debug_session_caching > 0) || ($this->debug_wrapper_dcom_calls > 0)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) LEAVING '.'<font color="purple">'.'returning data obtained from cache'.'</font>'.'<br />'); } 1014 return $cached_folder_status_info; 1015 } 1016 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) NO data found in cache (or it was stale) <br />'); } 1017 } 1018 1019 // Make Sure Stream Exists 1020 // multiple accounts means one stream may be open but another may not 1021 // "ensure_stream_and_folder" will verify for us, 1022 /*! 1023 @capability ensure_stream_and_folder WITHOUT changing folders 1024 @discussion folder STATUS data does not require opening the folder we want information about, 1025 THEREFOR we use a "$special_fldball" which has a$special_fldball["no_switch_away"] element of 1026 which is understood by function "ensure_stream_and_folder" to NOT CHANGE 1027 the selected folder, to make sure only that the stream exists and we are logged in to the mailserver, 1028 but the actual selected folder IN THIS SPECIAL CASE is not necessary to set. If we were to change the 1029 currently selected folder just to get stats, this would add additional complication to the concept of which folder 1030 we actually wanted to be selected, because "ensure_stream_and_folder" would set the "arg_value" for "folder" 1031 IF IT DID change the selected folder, which is NOT wanted nor needed in this case. 1032 @author Angles 1033 */ 1034 $special_fldball = array(); 1035 $special_fldball['acctnum'] = $fldball['acctnum']; 1036 $special_fldball['folder'] = $fldball['folder']; 1037 // STATUS does not require opening the folder we want information about 1038 $special_fldball['no_switch_away'] = True; 1039 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') call to $this->ensure_stream_and_folder(), $special_fldball ['.serialize($special_fldball).'] <br />'); } 1040 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') DO NOT pass a folderame IN THIS PARTICULAR case because getting folder status DOES NOT require opening that folder, "ensure_stream_and_folder" understands this.<br />'); } 1041 $this->ensure_stream_and_folder($special_fldball, 'get_folder_status_info'.' LINE '.__LINE__); 1042 1043 //$mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1044 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $fldball['acctnum']); 1045 $server_str = $this->get_arg_value('mailsvr_callstr', $fldball['acctnum']); 1046 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') will use $mailsvr_stream ['.serialize($mailsvr_stream).'] ; $server_str ['.$server_str.'] ; $fldball: '.serialize($fldball).' <br />'); } 1047 1048 $clean_folder_name = $this->prep_folder_in($fldball['folder']); 1049 $urlencoded_folder = $this->prep_folder_out($clean_folder_name); 1050 if (($this->debug_session_caching > 0) || ($this->debug_wrapper_dcom_calls > 0)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) <b>problem area: urlencoding only 1 time</b> $clean_folder_name ['.$clean_folder_name.'], $urlencoded_folder : ['.$urlencoded_folder.']);<br />'); } 1051 1052 // initialize return structure 1053 $return_data = Array(); 1054 $return_data['is_imap'] = False; 1055 $return_data['fldball'] = $fldball; 1056 $return_data['folder_checked'] = $clean_folder_name; 1057 $return_data['folder'] = $clean_folder_name; 1058 $return_data['alert_string'] = ''; 1059 $return_data['number_new'] = 0; 1060 $return_data['number_all'] = 0; 1061 // these are used to verify cached msg_list_array data, i.e. is it still any good, or is it stale 1062 $return_data['uidnext'] = 0; 1063 $return_data['uidvalidity'] = 0; 1064 $return_data['timestamp'] = time(); 1065 // FIXME: make this a "ensure_stream_and_folder" call, to make a login if needed 1066 //if (is_object($GLOBALS['phpgw_dcom_'.$fldball['acctnum']])) 1067 //{ 1068 // $mailbox_status = $GLOBALS['phpgw_dcom_'.$fldball['acctnum']]->dcom->status($mailsvr_stream,$server_str.$fldball['folder'],SA_ALL); 1069 //} 1070 // earlier we called $this->ensure_stream_and_folder, so stream *should* exist 1071 if (($this->debug_session_caching > 0) || ($this->debug_wrapper_dcom_calls > 0)) { $this->dbug->out('mail_msg(_wrappers): get_folder_status_info: ('.__LINE__.') calling $GLOBALS[phpgw_dcom_'.$fldball['acctnum'].']->dcom->status('.$mailsvr_stream.','.$server_str.$clean_folder_name.',SA_ALL)<br />'); } 1072 $mailbox_status = $GLOBALS['phpgw_dcom_'.$fldball['acctnum']]->dcom->status($mailsvr_stream,$server_str.$clean_folder_name,SA_ALL); 1073 if (($this->debug_session_caching > 2) || ($this->debug_wrapper_dcom_calls > 2)) { $this->dbug->out('mail_msg(_wrappers): get_folder_status_info: ('.__LINE__.') ->dcom->status returns: $mailbox_status DUMP', $mailbox_status); } 1074 1075 // cache validity data - will be used to cache msg_list_array data, which is good until UID_NEXT changes 1076 $return_data['uidnext'] = $mailbox_status->uidnext; 1077 $return_data['uidvalidity'] = $mailbox_status->uidvalidity; 1078 1079 $mail_server_type = $this->get_pref_value('mail_server_type', $fldball['acctnum']); 1080 if (($mail_server_type == 'imap') 1081 || ($mail_server_type == 'imaps')) 1082 { 1083 $return_data['is_imap'] = True; 1084 $return_data['number_new'] = $mailbox_status->unseen; 1085 $return_data['number_all'] = $mailbox_status->messages; 1086 if ($mailbox_status->unseen == 1) 1087 { 1088 $return_data['alert_string'] .= lang('You have 1 new message!'); 1089 } 1090 if ($mailbox_status->unseen > 1) 1091 { 1092 $return_data['alert_string'] .= lang('You have %1 new messages!',$mailbox_status->unseen); 1093 } 1094 if ($mailbox_status->unseen == 0) 1095 { 1096 $return_data['alert_string'] .= lang('You have no new messages'); 1097 } 1098 } 1099 else 1100 { 1101 $return_data['is_imap'] = False; 1102 // pop3 does not know what is "new" or not 1103 $return_data['number_new'] = $mailbox_status->messages; 1104 $return_data['number_all'] = $mailbox_status->messages; 1105 if ($mailbox_status->messages > 0) 1106 { 1107 $return_data['alert_string'] .= lang('You have messages!'); 1108 } 1109 elseif ($mailbox_status->messages == 0) 1110 { 1111 $return_data['alert_string'] .= lang('You have no new messages'); 1112 } 1113 else 1114 { 1115 $return_data['alert_string'] .= lang('error'); 1116 } 1117 } 1118 1119 if ($this->session_cache_extreme == False) 1120 { 1121 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (non-extreme mode) uses L1/class var cache, NO appsession cache used in non-extreme <br />'); } 1122 // cache data in a class var (L1 Cache) 1123 // USE L1 CACHE ONLY IN NON-EXTREME MODE 1124 if (($this->debug_session_caching > 2) || ($this->debug_wrapper_dcom_calls > 2)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (non-extreme mode) saving to L1 class var cache, $this->set_arg_value(folder_status_info, $return_data, '.$fldball['acctnum'].') ; $return_data dump:', $return_data); } 1125 //$this->set_arg_value('folder_status_info', $return_data, $fldball['acctnum']); 1126 $this->set_arg_value('["folder_status_info"]["'.$fldball['folder'].'"]', $return_data, $fldball['acctnum']); 1127 } 1128 else 1129 { 1130 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) uses appsession cache, no L1/class var cached is used in extreme mode <br />'); } 1131 if (($this->debug_session_caching > 1) || ($this->debug_wrapper_dcom_calls > 1)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) saving to session cache, $this->save_session_cache_item("folder_status_info", $return_data, $acctnum) NOTE that acctnum used here is ['.$acctnum.']<br />'); } 1132 if (($this->debug_session_caching > 2) || ($this->debug_wrapper_dcom_calls > 2)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') (extreme mode) $return_data DUMP', $return_data); } 1133 // NOTE that the $extra_keys param is generated FOR US in the function that saves this to appsession cache, we are doing that now 1134 $this->save_session_cache_item('folder_status_info', $return_data, $fldball['acctnum'], $fldball['folder']); 1135 } 1136 if (($this->debug_session_caching > 0) || ($this->debug_wrapper_dcom_calls > 0)) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') LEAVING, '.'<font color="red">'.'had contact mailserver to get data'.'</font>'.'<br />'); } 1137 return $return_data; 1138 } 1139 1140 // FIXME: change arg to fldball 1141 /*! 1142 @function phpgw_status 1143 @abstract ? 1144 @author Angles 1145 @discussion Debug with flag "debug_wrapper_dcom_calls" . FIXME change param to fldball. 1146 @access public 1147 */ 1148 function phpgw_status($feed_folder_long='') 1149 { 1150 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(wrappers): phpgw_status ('.__LINE__.'): ENTERING, $feed_folder_long ['.($feed_folder_long).']<br />'); } 1151 $fake_fldball = array(); 1152 $fake_fldball['acctnum'] = $this->get_acctnum(); 1153 $fake_fldball['folder'] = $feed_folder_long; 1154 $this->ensure_stream_and_folder($fake_fldball, 'phpgw_status'.' LINE '.__LINE__); 1155 $server_str = $this->get_arg_value('mailsvr_callstr'); 1156 $mailsvr_stream = $this->get_arg_value('mailsvr_stream'); 1157 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(wrappers): phpgw_status ('.__LINE__.'): calling $GLOBALS[phpgw_dcom_$fake_fldball[acctnum]('.$fake_fldball['acctnum'].')]->dcom->status($mailsvr_stream['.$mailsvr_stream.'],"$server_str"."$feed_folder_long"['.htmlspecialchars("$server_str"."$feed_folder_long").'],SA_ALL)<br />'); } 1158 $retval = $GLOBALS['phpgw_dcom_'.$fake_fldball['acctnum']]->dcom->status($mailsvr_stream,"$server_str"."$feed_folder_long",SA_ALL); 1159 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(wrappers): phpgw_status ('.__LINE__.'): LEAVING, returning $retval ['.serialize($retval).'] <br />'); } 1160 return $retval; 1161 } 1162 1163 /*! 1164 @function phpgw_server_last_error 1165 @abstract ? 1166 @author Angles 1167 @discussion Debug with flag "debug_wrapper_dcom_calls" 1168 @access public 1169 */ 1170 function phpgw_server_last_error($acctnum='') 1171 { 1172 if ((!isset($acctnum)) 1173 || ((string)$acctnum == '')) 1174 { 1175 $acctnum = $this->get_acctnum(); 1176 } 1177 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_server_last_error: ('.__LINE__.') calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->server_last_error()<br />'); } 1178 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->server_last_error(); 1179 } 1180 1181 /*! 1182 @function phpgw_ping 1183 @abstract ? 1184 @author Angles 1185 @discussion Debug with flag "debug_wrapper_dcom_calls" 1186 @access public 1187 */ 1188 function phpgw_ping($acctnum='') 1189 { 1190 if ((!isset($acctnum)) 1191 || ((string)$acctnum == '')) 1192 { 1193 $acctnum = $this->get_acctnum(); 1194 } 1195 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_ping ('.__LINE__.'): ENTERING, $acctnum ['.$acctnum.'], we DO NOT use "ensure_stream_and_folder" here because that would open the stream we are testing, making this test useless.<br />'); } 1196 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1197 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_ping ('.__LINE__.'): calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->noop_ping_test('.$mailsvr_stream.') <br />'); } 1198 $retval = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->noop_ping_test($mailsvr_stream); 1199 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_ping ('.__LINE__.'): LEAVING, returing $retval ['.serialize($retval).']<br />'); } 1200 return $retval; 1201 } 1202 1203 /*! 1204 @function phpgw_search 1205 @abstract ? 1206 @author Angles 1207 @discussion Debug with flag "debug_wrapper_dcom_calls" 1208 @access public 1209 */ 1210 function phpgw_search($fldball='', $criteria='', $flags='') 1211 { 1212 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_search ('.__LINE__.'): ENTERING, $fldball ['.serialize($fldball).']; $criteria ['.$criteria.']; $flags['.serialize($flags).'] <br />'); } 1213 $acctnum = (int)$fldball['acctnum']; 1214 if ((!isset($acctnum)) 1215 || ((string)$acctnum == '')) 1216 { 1217 $acctnum = $this->get_acctnum(); 1218 } 1219 $folder = $fldball['folder']; 1220 // if folder is blank, we *should* assume INBOX because filters always search the INBOX 1221 if ((!isset($folder)) 1222 || ((string)$folder == '')) 1223 { 1224 $folder = 'INBOX'; 1225 } 1226 // Make Sure Stream Exists 1227 // multiple accounts means one stream may be open but another may not 1228 // "ensure_stream_and_folder" will verify for us, 1229 $fake_fldball = array(); 1230 $fake_fldball['acctnum'] = $acctnum; 1231 $fake_fldball['folder'] = $folder; 1232 $this->ensure_stream_and_folder($fake_fldball, 'phpgw_search LINE '.__LINE__); 1233 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1234 1235 // now we have the stream and the desired folder open 1236 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_search ('.__LINE__.'): calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->i_search($mailsvr_stream['.$mailsvr_stream.'], $criteria['.$criteria.'],$flags['.serialize($flags).']) <br />'); } 1237 $retval = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->i_search($mailsvr_stream,$criteria,$flags); 1238 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_search ('.__LINE__.'): LEAVING, returing $retval ['.serialize($retval).']<br />'); } 1239 return $retval; 1240 } 1241 1242 /*! 1243 @function phpgw_createmailbox 1244 @abstract ? 1245 @param $target_fldball (array or type "fldball") NOTE: folder element SHOULD HAVE SERVER CALLSTR. 1246 @author Angles 1247 @access public 1248 */ 1249 function phpgw_createmailbox($target_fldball) 1250 { 1251 $acctnum = (int)$target_fldball['acctnum']; 1252 if ((!isset($acctnum)) 1253 || ((string)$acctnum == '')) 1254 { 1255 $acctnum = $this->get_acctnum(); 1256 } 1257 $folder = $target_fldball['folder']; 1258 // if folder is blank, we *should* assume INBOX because BUT mailsvr will give an error INBOX already exists 1259 if ((!isset($folder)) 1260 || ((string)$folder == '')) 1261 { 1262 $folder = 'INBOX'; 1263 } 1264 // Make Sure Stream Exists 1265 // multiple accounts means one stream may be open but another may not 1266 // "ensure_stream_and_folder" will verify for us, 1267 $fake_fldball = array(); 1268 $fake_fldball['acctnum'] = $acctnum; 1269 $fake_fldball['folder'] = $folder; 1270 // tell "ensure_stream_and_folder" that its NOT NECESSARY to switch TO this folder 1271 $fake_fldball['no_switch_away'] = True; 1272 $this->ensure_stream_and_folder($fake_fldball, 'phpgw_createmailbox LINE ('.__LINE__.')'); 1273 // if $folder dies not have the {SERVERNAME} then add it 1274 if (!strstr($folder, '}')) 1275 { 1276 $mailsvr_callstr = $this->get_arg_value('mailsvr_callstr', $acctnum); 1277 $folder = $mailsvr_callstr.$folder; 1278 } 1279 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1280 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->createmailbox($mailsvr_stream, $folder); 1281 } 1282 1283 /*! 1284 @function phpgw_createmailbox_ex 1285 @abstract ? 1286 @param $target_fldball (array or type "fldball") NOTE: folder element DOES NOT NEED THE SERVER CALLSTR. 1287 @discussion This function handles the traditional fldball better, a fldball["folder"] is NOT ever supposed to have 1288 a mailsvr_callstr, and IS ALWAYS urlencoded until just before we call the dcom class, when we urldecode it only 1289 at that point. This function assumes this behavior, so the typical fldball is supported by this function. 1290 This will be the future version of this function, code is migrating to this version. 1291 @author Angles 1292 @access public 1293 */ 1294 function phpgw_createmailbox_ex($target_fldball) 1295 { 1296 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('phpgw_createmailbox_ex('.__LINE__.'): ENTERING: raw $target_fldball arg ['.htmlspecialchars($target_fldball).']<br />'); } 1297 if ((isset($target_fldball['acctnum'])) 1298 && ((string)$target_fldball['acctnum'] != '')) 1299 { 1300 $target_fldball['acctnum'] = (int)$target_fldball['acctnum']; 1301 } 1302 else 1303 { 1304 $target_fldball['acctnum'] = $this->get_acctnum(); 1305 } 1306 $acctnum = $target_fldball['acctnum']; 1307 // if folder is blank, we *should* assume INBOX because BUT mailsvr will give an error INBOX already exists 1308 if ((isset($target_fldball['folder'])) 1309 || ((string)$target_fldball['folder'] != '')) 1310 { 1311 // good folder name, no change needed 1312 } 1313 else 1314 { 1315 $target_fldball['folder'] = 'INBOX'; 1316 } 1317 // Make Sure Stream Exists 1318 // multiple accounts means one stream may be open but another may not 1319 // "ensure_stream_and_folder" will verify for us, 1320 // tell "ensure_stream_and_folder" that its NOT NECESSARY to switch TO this folder 1321 $target_fldball['no_switch_away'] = True; 1322 $this->ensure_stream_and_folder($target_fldball, 'phpgw_createmailbox_ex LINE ('.__LINE__.')'); 1323 // if $folder dies not have the {SERVERNAME} then add it 1324 //$target_folder_clean = $this->prep_folder_in($target_fldball['folder']); 1325 $target_folder_clean = urldecode($target_fldball['folder']); 1326 if (!strstr($target_folder_clean, '}')) 1327 { 1328 $mailsvr_callstr = $this->get_arg_value('mailsvr_callstr', $acctnum); 1329 $target_folder_clean = $mailsvr_callstr.$target_folder_clean; 1330 } 1331 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1332 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('phpgw_createmailbox_ex('.__LINE__.'): calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->createmailbox('.serialize($mailsvr_stream).', '.htmlspecialchars($target_folder_clean).'<br />'); } 1333 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->createmailbox($mailsvr_stream, $target_folder_clean); 1334 } 1335 1336 /*! 1337 @function phpgw_deletemailbox 1338 @abstract ? 1339 @author Angles 1340 @access public 1341 */ 1342 function phpgw_deletemailbox($target_fldball) 1343 { 1344 $this->ensure_stream_and_folder($target_fldball, 'phpgw_deletemailbox'.' LINE '.__LINE__); 1345 $acctnum = $target_fldball['acctnum']; 1346 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1347 $folder = $target_fldball['folder']; 1348 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->deletemailbox($mailsvr_stream, $folder); 1349 } 1350 1351 /*! 1352 @function phpgw_deletemailbox_ex 1353 @abstract ? 1354 @param $target_fldball (array or type "fldball") NOTE: folder element DOES NOT NEED THE SERVER CALLSTR. 1355 @discussion This function handles the traditional fldball better, a fldball["folder"] is NOT ever supposed to have 1356 a mailsvr_callstr, and IS ALWAYS urlencoded until just before we call the dcom class, when we urldecode it only 1357 at that point. This function assumes this behavior, so the typical fldball is supported by this function. 1358 This will be the future version of this function, code is migrating to this version. 1359 @author Angles 1360 @access public 1361 */ 1362 function phpgw_deletemailbox_ex($target_fldball) 1363 { 1364 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('phpgw_deletemailbox_ex('.__LINE__.'): ENTERING: raw $target_fldball arg ['.htmlspecialchars($target_fldball).']<br />'); } 1365 if ((isset($target_fldball['acctnum'])) 1366 && ((string)$target_fldball['acctnum'] != '')) 1367 { 1368 $target_fldball['acctnum'] = (int)$target_fldball['acctnum']; 1369 } 1370 else 1371 { 1372 $target_fldball['acctnum'] = $this->get_acctnum(); 1373 } 1374 $acctnum = $target_fldball['acctnum']; 1375 // if folder is blank, we *should* assume INBOX because BUT mailsvr will give an error INBOX already exists 1376 if ((isset($target_fldball['folder'])) 1377 || ((string)$target_fldball['folder'] != '')) 1378 { 1379 // good folder name, no change needed 1380 } 1381 else 1382 { 1383 $target_fldball['folder'] = 'INBOX'; 1384 } 1385 // Make Sure Stream Exists 1386 // multiple accounts means one stream may be open but another may not 1387 // "ensure_stream_and_folder" will verify for us, 1388 // tell "ensure_stream_and_folder" that its NOT NECESSARY to switch TO this folder 1389 $target_fldball['no_switch_away'] = True; 1390 $this->ensure_stream_and_folder($target_fldball, 'phpgw_deletemailbox_ex LINE ('.__LINE__.')'); 1391 // if $folder dies not have the {SERVERNAME} then add it 1392 //$target_folder_clean = $this->prep_folder_in($target_fldball['folder']); 1393 $target_folder_clean = urldecode($target_fldball['folder']); 1394 if (!strstr($target_folder_clean, '}')) 1395 { 1396 $mailsvr_callstr = $this->get_arg_value('mailsvr_callstr', $acctnum); 1397 $target_folder_clean = $mailsvr_callstr.$target_folder_clean; 1398 } 1399 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1400 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('phpgw_deletemailbox_ex('.__LINE__.'): calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->deletemailbox('.serialize($mailsvr_stream).', '.htmlspecialchars($target_folder_clean).'<br />'); } 1401 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->deletemailbox($mailsvr_stream, $target_folder_clean); 1402 } 1403 1404 /*! 1405 @function phpgw_renamemailbox 1406 @abstract ? 1407 @author Angles 1408 @access public 1409 */ 1410 function phpgw_renamemailbox($source_fldball,$target_fldball) 1411 { 1412 $this->ensure_stream_and_folder($source_fldball, 'phpgw_renamemailbox'.' LINE '.__LINE__); 1413 $acctnum = (int)$source_fldball['acctnum']; 1414 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1415 $folder_old = $source_fldball['folder']; 1416 $folder_new = $target_fldball['folder']; 1417 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->renamemailbox($mailsvr_stream, $folder_old, $folder_new); 1418 } 1419 1420 /*! 1421 @function phpgw_renamemailbox_ex 1422 @abstract ? 1423 @param $target_fldball (array or type "fldball") NOTE: folder element DOES NOT NEED THE SERVER CALLSTR. 1424 @discussion This function handles the traditional fldball better, a fldball["folder"] is NOT ever supposed to have 1425 a mailsvr_callstr, and IS ALWAYS urlencoded until just before we call the dcom class, when we urldecode it only 1426 at that point. This function assumes this behavior, so the typical fldball is supported by this function. 1427 This will be the future version of this function, code is migrating to this version. 1428 @author Angles 1429 @access public 1430 */ 1431 function phpgw_renamemailbox_ex($source_fldball,$target_fldball) 1432 { 1433 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('phpgw_renamemailbox_ex('.__LINE__.'): ENTERING<br />'); } 1434 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('phpgw_renamemailbox_ex('.__LINE__.'): raw $source_fldball arg ['.htmlspecialchars($source_fldball).']; raw $target_fldball arg ['.htmlspecialchars($target_fldball).']<br />'); } 1435 if ((isset($target_fldball['acctnum'])) 1436 && ((string)$target_fldball['acctnum'] != '')) 1437 { 1438 $target_fldball['acctnum'] = (int)$target_fldball['acctnum']; 1439 } 1440 else 1441 { 1442 $target_fldball['acctnum'] = $this->get_acctnum(); 1443 } 1444 $acctnum = $target_fldball['acctnum']; 1445 // if folder is blank, we *should* assume INBOX because BUT mailsvr will give an error INBOX already exists 1446 if ((isset($target_fldball['folder'])) 1447 || ((string)$target_fldball['folder'] != '')) 1448 { 1449 // good folder name, no change needed 1450 } 1451 else 1452 { 1453 $target_fldball['folder'] = 'INBOX'; 1454 } 1455 // Make Sure Stream Exists 1456 // multiple accounts means one stream may be open but another may not 1457 // "ensure_stream_and_folder" will verify for us, 1458 // tell "ensure_stream_and_folder" that its NOT NECESSARY to switch TO this folder 1459 $target_fldball['no_switch_away'] = True; 1460 $this->ensure_stream_and_folder($target_fldball, 'phpgw_renamemailbox_ex LINE ('.__LINE__.')'); 1461 // if $folder dies not have the {SERVERNAME} then add it 1462 //$target_folder_clean = $this->prep_folder_in($target_fldball['folder']); 1463 $target_folder_clean = urldecode($target_fldball['folder']); 1464 if (!strstr($target_folder_clean, '}')) 1465 { 1466 $mailsvr_callstr = $this->get_arg_value('mailsvr_callstr', $acctnum); 1467 $target_folder_clean = $mailsvr_callstr.$target_folder_clean; 1468 } 1469 1470 // SOURCE FOLDER NAME 1471 //the folder we are renaming MUST BE from the same account 1472 // so we only need to clean up its name 1473 if ((isset($source_fldball['folder'])) 1474 || ((string)$source_fldball['folder'] != '')) 1475 { 1476 // good folder name, no change needed 1477 } 1478 else 1479 { 1480 $source_fldball['folder'] = 'INBOX'; 1481 } 1482 $source_folder_clean = urldecode($source_fldball['folder']); 1483 // if $folder dies not have the {SERVERNAME} then add it 1484 if (!strstr($source_folder_clean, '}')) 1485 { 1486 $mailsvr_callstr = $this->get_arg_value('mailsvr_callstr', $acctnum); 1487 $source_folder_clean = $mailsvr_callstr.$source_folder_clean; 1488 } 1489 1490 // OK WE are ready to do it! 1491 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1492 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('phpgw_renamemailbox_ex('.__LINE__.'): calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->renamemailbox('.serialize($mailsvr_stream).', '.htmlspecialchars($source_folder_clean).', '.htmlspecialchars($target_folder_clean).'<br />'); } 1493 //return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->createmailbox($mailsvr_stream, $target_folder_clean); 1494 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->renamemailbox($mailsvr_stream, $source_folder_clean, $target_folder_clean); 1495 } 1496 1497 /*! 1498 @function phpgw_listmailbox 1499 @abstract ? 1500 @author Angles 1501 @discussion Debug with flag "debug_wrapper_dcom_calls" 1502 @access public 1503 */ 1504 function phpgw_listmailbox($ref,$pattern,$acctnum) 1505 { 1506 if (!(isset($acctnum)) 1507 || ((string)$acctnum == '')) 1508 { 1509 $acctnum = $this->get_acctnum(); 1510 } 1511 // Make Sure Stream Exists 1512 // multiple accounts means one stream may be open but another may not 1513 // "ensure_stream_and_folder" will verify for us, 1514 // folder logged into does not matter for listmailbox, so pass $fake_fldball['no_switch_away'] = True 1515 $fake_fldball = array(); 1516 $fake_fldball['acctnum'] = $acctnum; 1517 $fake_fldball['folder'] = ''; 1518 $fake_fldball['no_switch_away'] = True; 1519 $this->ensure_stream_and_folder($fake_fldball, 'phpgw_listmailbox'); 1520 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1521 1522 // ... so stream exists, do the transaction ... 1523 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_listmailbox ('.__LINE__.'): calling $GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->listmailbox($mailsvr_stream['.$mailsvr_stream.'],$ref['.$ref.'], $pattern['.$pattern.']); <br />'); } 1524 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->listmailbox($mailsvr_stream,$ref,$pattern); 1525 } 1526 1527 /*! 1528 @function phpgw_append 1529 @abstract ? 1530 @author Angles 1531 @discussion Debug with flag "debug_wrapper_dcom_calls" 1532 @access public 1533 */ 1534 function phpgw_append($folder="Sent", $message, $flags=0) 1535 { 1536 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_append: ('.__LINE__.') ENTERING, folder: '.$folder.'<br />'); } 1537 1538 $server_str = $this->get_arg_value('mailsvr_callstr'); 1539 1540 // --- does the target folder actually exist ? --- 1541 // strip {server_str} string if it's there 1542 $folder = $this->ensure_no_brackets($folder); 1543 // attempt to find a folder match in the lookup list 1544 $official_folder_long = $this->folder_lookup('', $folder); 1545 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_append: ('.__LINE__.') $official_folder_long: '.$official_folder_long.'<br />'); } 1546 if ($official_folder_long != '') 1547 { 1548 $havefolder = True; 1549 } 1550 else 1551 { 1552 $havefolder = False; 1553 } 1554 1555 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_append: ('.__LINE__.') $havefolder ['.serialize($havefolder).']<br />'); } 1556 if ($havefolder == False) 1557 { 1558 // add whatever namespace we believe should exist 1559 // (remember the lookup failed, so we have to guess here) 1560 $folder_long = $this->get_folder_long($folder); 1561 // create the specified target folder so it will exist 1562 //$this->createmailbox($mailsvr_stream,"$server_str"."$folder_long"); 1563 //$this->phpgw_createmailbox("$server_str"."$folder_long"); 1564 $fake_fldball = array(); 1565 $fake_fldball['folder'] = $server_str.$folder_long; 1566 $fake_fldball['acctnum'] = $this->get_acctnum(); 1567 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_append: ('.__LINE__.') calling $this->phpgw_createmailbox('.serialize($fake_fldball).')<br />'); } 1568 $this->phpgw_createmailbox($fake_fldball); 1569 1570 // try again to get the real long folder name of the just created trash folder 1571 $official_folder_long = $this->folder_lookup('', $folder); 1572 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_append: ('.__LINE__.') $official_folder_long: '.$official_folder_long.'<br />'); } 1573 // did the folder get created and do we now have the official full name of that folder? 1574 if ($official_folder_long != '') 1575 { 1576 $havefolder = True; 1577 } 1578 } 1579 1580 // at this point we've tries 2 time to obtain the "server approved" long name for the target folder 1581 // even tries creating it if necessary 1582 // if we have the name, append the message to that folder 1583 if (($havefolder == True) 1584 && ($official_folder_long != '')) 1585 { 1586 // delete appsession msg array data thAt is now stale 1587 // WE DO NOT GUESS ABOUT APPENDS, WE EXPIRE THE DATA AND GET FRESH 1588 //$this->expire_session_cache_item('msgball_list'); 1589 $target_fldball = array(); 1590 $target_fldball['folder'] = $official_folder_long; 1591 $target_fldball['acctnum'] = $this->get_acctnum(); 1592 $this->event_msg_append($target_fldball, 'phpgw_append'.' LINE '.__LINE__); 1593 1594 $this->ensure_stream_and_folder($target_fldball, 'phpgw_append'.' LINE '.__LINE__); 1595 $mailsvr_stream = $this->get_arg_value('mailsvr_stream'); 1596 // do the append 1597 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_append: $GLOBALS["phpgw_dcom_'.$target_fldball['acctnum'].']->dcom->append('.$mailsvr_stream.', '."$server_str"."$official_folder_long".', $message, '.$flags.') '); } 1598 //$acctnum: ['.$acctnum.'] $mailsvr_stream: ['.$mailsvr_stream.'] $msgnum: ['.$msgnum.'] $mailbox: ['.htmlspecialchars($mailbox).']<br />'; } 1599 $retval = $GLOBALS['phpgw_dcom_'.$target_fldball['acctnum']]->dcom->append($mailsvr_stream, "$server_str"."$official_folder_long", $message, $flags); 1600 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_append ('.__LINE__.'): LEAVING, returning $retval ['.serialize($retval).']<br />'); } 1601 return $retval; 1602 } 1603 else 1604 { 1605 // we do not have the official long folder name for the target folder 1606 // we can NOT append the message to a folder name we are not SURE is corrent 1607 // it will fail HANG the browser for a while 1608 // so just SKIP IT 1609 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_append ('.__LINE__.'): LEAVING on error, returning FALSE, unable to get good foldername, unable to append <br />'); } 1610 return False; 1611 } 1612 } 1613 1614 /*! 1615 @function phpgw_mail_move 1616 @abstract DEPRECIATED - NO LONGER USED. Use "industrial_interacct_mail_move" instead. 1617 @author Angles 1618 @access public 1619 */ 1620 function phpgw_mail_move($msg_list,$mailbox) 1621 { 1622 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_mail_move: (DEPRECIATED) ENTERING<br />'); } 1623 // OLD FUNCTION does not provide enough information, all we can do is expire 1624 $this->event_msg_move_or_delete(array(), 'phpgw_mail_move'); 1625 // delete session msg array data thAt is now stale 1626 //$this->expire_session_cache_item('msgball_list'); 1627 1628 $retval = $GLOBALS['phpgw_dcom_'.$this->acctnum]->dcom->mail_move($this->get_arg_value('mailsvr_stream'), $msg_list, $mailbox); 1629 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_mail_move: (DEPRECIATED) LEAVING, $retval ['.serialize($retval).'] <br />'); } 1630 return $retval; 1631 } 1632 1633 /*! 1634 @function interacct_mail_move 1635 @abstract DEPRECIATED - BEING PHASED OUT. Use "industrial_interacct_mail_move" instead. 1636 @author Angles 1637 @access public 1638 */ 1639 function interacct_mail_move($mov_msgball='', $to_fldball='') 1640 { 1641 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): interacct_mail_move: ENTERING<br />'); } 1642 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): interacct_mail_move: $mov_msgball ['.serialize($mov_msgball).'] ; $to_fldball ['.serialize($to_fldball).']<br />'); } 1643 // this needs A LOT of work!!! do not rely on this yet 1644 1645 // delete session msg array data thAt is now stale 1646 $this->event_msg_move_or_delete($mov_msgball, 'interacct_mail_move'.' LINE '.__LINE__, $to_fldball); 1647 //$this->expire_session_cache_item('msgball_list'); 1648 1649 // Note: Only call this function with ONE msgball at a time, i.e. NOT a list of msgballs 1650 $acctnum = (int)$mov_msgball['acctnum']; 1651 if (!(isset($acctnum)) 1652 || ((string)$acctnum == '')) 1653 { 1654 $acctnum = $this->get_acctnum(); 1655 } 1656 $this->ensure_stream_and_folder($mov_msgball, 'interacct_mail_move'.' LINE '.__LINE__); 1657 1658 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): interacct_mail_move:'.' LINE '.__LINE__.' If this is a move to a DIFFERENT account, then THIS FUNCTION is the WRONG ONE to use, it can not handle that<br />'); } 1659 1660 // NO - this function only works with folders within the same account 1661 //$this->ensure_stream_and_folder($to_fldball, 'interacct_mail_move'.' LINE '.__LINE__); 1662 1663 //$mailsvr_stream = (int)$this->get_arg_value('mailsvr_stream', $acctnum); 1664 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 1665 $msgnum = (string)$mov_msgball['msgnum']; 1666 $mailbox = $to_fldball['folder']; 1667 // the acctnum we are moving FROM *may* be different from the acctnum we are moving TO 1668 // that requires a fetch then an append - FIXME!!! 1669 1670 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): interacct_mail_move: $acctnum: ['.$acctnum.'] $mailsvr_stream: ['.$mailsvr_stream.'] $msgnum: ['.$msgnum.'] $mailbox: ['.htmlspecialchars($mailbox).']<br />'); } 1671 $retval = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->mail_move($mailsvr_stream ,$msgnum, $mailbox); 1672 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): interacct_mail_move: LEAVING, $retval ['.serialize($retval).'] <br />'); } 1673 return $retval; 1674 } 1675 1676 /*! 1677 @function industrial_interacct_mail_move 1678 @abstract ? 1679 @param $mov_msgball (array of type msgball) the message the will be moved. 1680 @param $to_fldball (array of type fldball) the target of the move. 1681 @author Angles 1682 @discussion ? 1683 @access public 1684 */ 1685 function industrial_interacct_mail_move($mov_msgball='', $to_fldball='') 1686 { 1687 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): industrial_interacct_mail_move: ENTERING, handing off to $this->buffer_move_commands()<br />'); } 1688 // Note: Only call this function with ONE msgball at a time, i.e. NOT a list of msgballs 1689 // then we buffer each command with this function 1690 $this->buffer_move_commands($mov_msgball, $to_fldball); 1691 1692 //if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): industrial_interacct_mail_move ('.__LINE__.'): ok, now add this folder to this accounts "expunge_folders" arg via "track_expungable_folders"<br />'); } 1693 // do this during actual moves 1694 $this->track_expungable_folders($mov_msgball); 1695 1696 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): industrial_interacct_mail_move: LEAVING, return True so we do not confuse calling process<br />'); } 1697 return True; 1698 } 1699 1700 /*! 1701 @function buffer_mail_move_commands 1702 @abstract ? 1703 @param $mov_msgball (array of type msgball) the message the will be moved. 1704 @param $to_fldball (array of type fldball) the target of the move. 1705 @author Angles 1706 @discussion ? 1707 @access public 1708 */ 1709 function buffer_move_commands($mov_msgball='', $to_fldball='') 1710 { 1711 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): ENTERING<br />'); } 1712 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): $mov_msgball ['.serialize($mov_msgball).'] $to_fldball ['.serialize($to_fldball).']<br />'); } 1713 1714 // assemble the URI like string that will hold the command move request instructions 1715 $this_move_data = ''; 1716 $this_move_data = 1717 'mov_msgball[acctnum]='.$mov_msgball['acctnum'] 1718 .'&mov_msgball[folder]='.$mov_msgball['folder'] 1719 .'&to_fldball[acctnum]='.$to_fldball['acctnum'] 1720 .'&to_fldball[folder]='.$to_fldball['folder'] 1721 .'&mov_msgball[msgnum]='.$mov_msgball['msgnum']; 1722 1723 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): $this_move_data ['.htmlspecialchars($this_move_data).']<br />'); } 1724 if ($this->debug_wrapper_dcom_calls > 2) 1725 { 1726 $this_move_balls = array(); 1727 parse_str($this_move_data, $this_move_balls); 1728 //echo 'mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): parse_str($this_move_data, $this_move_balls) $this_move_balls DUMP <pre>'; print_r($this_move_balls); echo '</pre>'; 1729 $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): parse_str($this_move_data, $this_move_balls) $this_move_balls DUMP:', $this_move_balls); 1730 } 1731 1732 // add this to the array 1733 $this->buffered_move_commmands[$this->buffered_move_commmands_count] = $this_move_data; 1734 // increase the count, avoids calling count() every trip thru this loop 1735 $this->buffered_move_commmands_count++; 1736 if ($this->debug_wrapper_dcom_calls > 2) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): added new item to array, new $this->buffered_move_commmands DUMP:', $this->buffered_move_commmands); } 1737 1738 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): LEAVING: did add $this_move_data to array, new array count $this->buffered_move_commmands_count: ['.$this->buffered_move_commmands_count.'], "from" acctnum is ['.$mov_msgball['acctnum'].']<br />'); } 1739 return; 1740 } 1741 1742 /*! 1743 @function buffer_delete_commands 1744 @abstract ? 1745 @param $mov_msgball (array of type msgball) the message the will be moved. 1746 @param $to_fldball (array of type fldball) the target of the move. 1747 @author Angles 1748 @discussion ? 1749 @access public 1750 */ 1751 function buffer_delete_commands($mov_msgball='', $to_fldball='') 1752 { 1753 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): ENTERING<br />'); } 1754 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): $mov_msgball ['.serialize($mov_msgball).'] $to_fldball ['.serialize($to_fldball).']<br />'); } 1755 1756 // assemble the URI like string that will hold the command move request instructions 1757 $this_move_data = ''; 1758 $this_move_data = 1759 'mov_msgball[acctnum]='.$mov_msgball['acctnum'] 1760 .'&mov_msgball[folder]='.$mov_msgball['folder'] 1761 .'&to_fldball[acctnum]='.$to_fldball['acctnum'] 1762 .'&to_fldball[folder]='.$to_fldball['folder'] 1763 .'&mov_msgball[msgnum]='.$mov_msgball['msgnum']; 1764 1765 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): $this_move_data ['.htmlspecialchars($this_move_data).']<br />'); } 1766 if ($this->debug_wrapper_dcom_calls > 2) 1767 { 1768 $this_move_balls = array(); 1769 parse_str($this_move_data, $this_move_balls); 1770 //echo 'mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): parse_str($this_move_data, $this_move_balls) $this_move_balls DUMP <pre>'; print_r($this_move_balls); echo '</pre>'; 1771 $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): parse_str($this_move_data, $this_move_balls) $this_move_balls DUMP:', $this_move_balls); 1772 } 1773 1774 // add this to the array 1775 $this->buffered_move_commmands[$this->buffered_move_commmands_count] = $this_move_data; 1776 // increase the count, avoids calling count() every trip thru this loop 1777 $this->buffered_move_commmands_count++; 1778 if ($this->debug_wrapper_dcom_calls > 2) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): added new item to array, new $this->buffered_move_commmands DUMP:', $this->buffered_move_commmands); } 1779 1780 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): buffer_move_commands ('.__LINE__.'): LEAVING: did add $this_move_data to array, new array count $this->buffered_move_commmands_count: ['.$this->buffered_move_commmands_count.'], "from" acctnum is ['.$mov_msgball['acctnum'].']<br />'); } 1781 return; 1782 } 1783 1784 /* 1785Array 1786( 1787 [0] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=38 1788 [1] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=66 1789 [2] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=28 1790 [3] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=29 1791 [4] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=31 1792 [5] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=32 1793 [6] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=33 1794 [7] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=34 1795 [8] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=35 1796 [9] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=24 1797 [10] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=26 1798 [11] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=27 1799 [12] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=23 1800 [13] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=13 1801 [14] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=14 1802 [15] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=15 1803 [16] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=16 1804 [17] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=17 1805 [18] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=18 1806 [19] => mov_msgball[acctnum]=5&mov_msgball[folder]=INBOX&to_fldball[acctnum]=5&to_fldball[folder]=mail%2FPostmaster&mov_msgball[msgnum]=19 1807) 1808 1809Array 1810( 1811 [mov_msgball] => Array 1812 ( 1813 [acctnum] => 5 1814 [folder] => INBOX 1815 [msgnum] => 19 1816 ) 1817 1818 [to_fldball] => Array 1819 ( 1820 [acctnum] => 5 1821 [folder] => mail/Postmaster 1822 ) 1823 1824) 1825 */ 1826 1827 1828 /*! 1829 @function flush_buffered_move_commmands 1830 @abstract ? 1831 @author Angles 1832 @discussion ? 1833 @access public 1834 */ 1835 function flush_buffered_move_commmands($called_by='not_specified') 1836 { 1837 $do_it_for_real = True; 1838 //$do_it_for_real = False; 1839 1840 // we tell the cache to flush and surn off during a big move, if we find a move is requested, just call the notice once. 1841 $did_give_big_move_notice = False; 1842 1843 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): ENTERING, called by ['.$called_by.'], <br />'); } 1844 // leave now if nothing is in the buffered command array 1845 if ($this->buffered_move_commmands_count == 0) 1846 { 1847 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): LEAVING, nothing to do, return False, $this->buffered_move_commmands_count: ['.$this->buffered_move_commmands_count.']<br />'); } 1848 return False; 1849 } 1850 1851 // is this a "big move" 1852 //$big_move_thresh = 2; 1853 $big_move_thresh = 10; 1854 $is_big_move = False; 1855 if ($this->buffered_move_commmands_count > $big_move_thresh) 1856 { 1857 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): issue $this->event_begin_big_move because $big_move_thresh: ['.$big_move_thresh.'] $this->buffered_move_commmands_count: ['.$this->buffered_move_commmands_count.']<br />'); } 1858 $this->event_begin_big_move(array(), 'mail_msg(_wrappers): buffered_move_commmands: LINE '.__LINE__); 1859 $is_big_move = True; 1860 } 1861 // Sort will GROUP THE MOVES AS MUCH AS POSSIBLE RIGHT NOW 1862 // the way we put the strings in the $this->buffered_move_commmands is designed to be 1863 // used by sort to end up grouping similar moves for us inside the array, 1864 // grouping by _from_acctnum__from_folder__to_acctnum__to_folder__msgnum 1865 // so similar moves are grouped as much as possible, simply, by calling sort. 1866 reset($this->buffered_move_commmands); 1867 sort($this->buffered_move_commmands); 1868 // trying to get single digit integers grouped with each other, but I do not think this next function is any better at that 1869 //sort($this->buffered_move_commmands, SORT_NUMERIC & SORT_STRING); 1870 // we know the FROM acct num is the same for all commands 1871 // we know the list is sorted so all FROM folders are together, and then the TO_FOLDERS 1872 // note the the "del_pseudo_folder" also will be grouped together, later we determing what command to call whether move or straight delete 1873 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): we have delete instructions(s) to be processed, (sorted) $this->buffered_move_commmands DUMP:', $this->buffered_move_commmands); } 1874 1875 $grouped_move_balls = array(); 1876 // group the commands 1877 for ($x=0; $x < $this->buffered_move_commmands_count; $x++) 1878 { 1879 $this_move_balls = array(); 1880 parse_str($this->buffered_move_commmands[$x], $this_move_balls); 1881 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands: loop ['.$x.']: $this_move_balls: ['.htmlspecialchars(serialize($this_move_balls)).']<br />'); } 1882 // NOTE PARSE_STR ***WILL ADD SLASHES*** TO ESCAPE QUOTES 1883 // NO MATTER WHAT YOUR MAGIC SLASHES SETTING IS 1884 if ($this->debug_args_input_flow > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands: loop ['.$x.']: NOTE PARSE_STR ***WILL ADD SLASHES*** TO ESCAPE QUOTES NO MATTER WHAT YOUR MAGIC SLASHES SETTING IS **stripping slashes NOW***'); } 1885 if (isset($this_move_balls['mov_msgball']['folder'])) 1886 { 1887 $this_move_balls['mov_msgball']['folder'] = stripslashes($this_move_balls['mov_msgball']['folder']); 1888 } 1889 if (isset($this_move_balls['to_fldball']['folder'])) 1890 { 1891 $this_move_balls['to_fldball']['folder'] = stripslashes($this_move_balls['to_fldball']['folder']); 1892 } 1893 1894 // no matter what, we know we are going to move this message, so notify cache if needed 1895 // IF WE ISSUED A BIG MOVE NOTICE THEN THE CACHE IS FLUSHED ALREADY 1896 if ($is_big_move == False) 1897 { 1898 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands: loop ['.$x.'] $is_big_move: ['.serialize($is_big_move).'] so calling $this->event_msg_move_or_delete()<br />'); } 1899 $this->event_msg_move_or_delete($this_move_balls['mov_msgball'], 'flush_buffered_move_commmands'.' LINE: '.__LINE__, $this_move_balls['to_fldball']); 1900 } 1901 1902 // --- does the FROM folder match the previous one in the list? --- 1903 $count_grouped = count($grouped_move_balls); 1904 // make sure at lease one move is in this array, we need at least on previous to compare to, else just add it to start an array 1905 if ($count_grouped == 0) 1906 { 1907 // add it to the array to get it started 1908 //array_push($grouped_move_balls, $this_move_balls); 1909 $grouped_move_balls[0] = $this_move_balls; 1910 if ($this->buffered_move_commmands_count > 1) 1911 { 1912 // SKIP TO NEXT LOOP, we need to compare (try to group) b4 we know to issue the actual move command or not 1913 // NOTE: CONTINUE 1914 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands('.__LINE__.'): loop ['.$x.']: added item to array, skip to next iteration<br />'); } 1915 continue; 1916 } 1917 else 1918 { 1919 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands('.__LINE__.'): loop ['.$x.']: added item to array, NOT skipping to next iteration because there is only 1 item in array ['.$this->buffered_move_commmands_count.']<br />'); } 1920 } 1921 } 1922 //elseif (($count_grouped > 0) 1923 //&& ($grouped_move_balls[$count_grouped-1]['mov_msgball']['folder'] == $this_move_balls['mov_msgball']['folder']) 1924 //&& ($grouped_move_balls[$count_grouped-1]['to_fldball']['folder'] == $this_move_balls['to_fldball']['folder']) 1925 //) 1926 elseif (($count_grouped > 0) 1927 && ($x != $this->buffered_move_commmands_count-1) 1928 && ($grouped_move_balls[$count_grouped-1]['mov_msgball']['acctnum'] == $this_move_balls['mov_msgball']['acctnum']) 1929 && ($grouped_move_balls[$count_grouped-1]['mov_msgball']['folder'] == $this_move_balls['mov_msgball']['folder']) 1930 && ($grouped_move_balls[$count_grouped-1]['to_fldball']['folder'] == $this_move_balls['to_fldball']['folder']) 1931 ) 1932 { 1933 // PASSES the "is grouped" test, add to the "grouped array" 1934 // AND this is NOT the last item in buffered_move_commmands (that would require action, not another loop) 1935 array_push($grouped_move_balls, $this_move_balls); 1936 // NOTE: CONTINUE 1937 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands('.__LINE__.'): loop ['.$x.']: added item to array, skip to next iteration<br />'); } 1938 continue; 1939 } 1940 elseif (($count_grouped > 0) 1941 && ($x == $this->buffered_move_commmands_count-1) 1942 && ($grouped_move_balls[$count_grouped-1]['mov_msgball']['acctnum'] == $this_move_balls['mov_msgball']['acctnum']) 1943 && ($grouped_move_balls[$count_grouped-1]['mov_msgball']['folder'] == $this_move_balls['mov_msgball']['folder']) 1944 && ($grouped_move_balls[$count_grouped-1]['to_fldball']['folder'] == $this_move_balls['to_fldball']['folder']) 1945 ) 1946 { 1947 // PASSES the "is grouped" test, add to the "grouped array" 1948 // AND this is the FINAL ITEM, so KEEP GOING down to the code to issue the actual move command 1949 array_push($grouped_move_balls, $this_move_balls); 1950 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands('.__LINE__.'): loop ['.$x.']: added item to array, but NOT skipping to next iteration<br />'); } 1951 // DO NOT issue "CONTINUE" here 1952 } 1953 else 1954 { 1955 //if ($this->debug_wrapper_dcom_calls > 1) { echo ' * mail_msg(_wrappers): flush_buffered_move_commmands('.__LINE__.'): loop ['.$x.']: UNHANDLED if .. then, $$grouped_move_balls[$count_grouped-1] DUMP<pre>'; print_r($grouped_move_balls[$count_grouped-1]); echo "\r\n".' $$this_move_balls DUMP'; print_r($this_move_balls); echo '</pre>' ; } 1956 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands('.__LINE__.'): loop ['.$x.']: UNHANDLED if .. then, $$grouped_move_balls[$count_grouped-1] DUMP', $grouped_move_balls[$count_grouped-1]); } 1957 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * mail_msg(_wrappers): flush_buffered_move_commmands('.__LINE__.'): loop ['.$x.']: UNHANDLED if .. then, $$this_move_balls DUMP', $this_move_balls); } 1958 } 1959 1960 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: if we get here, we can not group anymore, or the series just ended, so issue the command now<br />'); } 1961 // OK if we are here then we know this 1962 // * "grouped_move_balls" has at least one command in it 1963 // ** the current command does not match the preious one in terms or grouping them together 1964 // ** OR the urrent command is the final in the $this->buffered_move_commmands array 1965 // THEREFOR: 1966 // 1) we need now make a IMAP command that has all the grouped msgnums from grouped_move_balls 1967 // 2) if NOT the final item in $this->buffered_move_commmands we need to 1968 // 2a) then we need to clear grouped_move_balls and ADD this_move_balls to it to start a new grouping array 1969 // 2b) then run again thru the loop after that 1970 1971 // update this, this loop may have added to it since we last checked this 1972 $count_grouped = count($grouped_move_balls); 1973 1974 // IF THIS MOVE IS TO ANOTHER ACCOUNT, HAND IT OFF RIGHT NOW 1975 if ( ($count_grouped = 1) 1976 && ((int)$grouped_move_balls[0]['mov_msgball']['acctnum'] != (int)$grouped_move_balls[0]['to_fldball']['acctnum']) ) 1977 { 1978 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): ($do_it_for_real is '.serialize($do_it_for_real).'): 1 single **DIFFERENT** Account Move item in $grouped_move_balls, hand off to "single_interacct_mail_move"<br />'); } 1979 if ($do_it_for_real == True) 1980 { 1981 $this->single_interacct_mail_move($grouped_move_balls[$count_grouped-1]['mov_msgball'], $grouped_move_balls[$count_grouped-1]['to_fldball']); 1982 } 1983 } 1984 elseif ( ($count_grouped > 1) 1985 && ((int)$grouped_move_balls[$count_grouped-1]['mov_msgball']['acctnum'] != (int)$grouped_move_balls[$count_grouped-1]['to_fldball']['acctnum']) ) 1986 { 1987 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): LEAVING with ERROR: ERROR: unhandled if .. then, $grouped_move_balls has multiple items but accounts do not match, different accounts should be handled one at a time!!!<br />'); } 1988 echo 'mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): LEAVING with ERROR: unhandled if .. then, $grouped_move_balls has multiple items but accounts do not match, different accounts should be handled one at a time!!!<br />'; 1989 return False; 1990 } 1991 else 1992 { 1993 // FIXME: some logic below relies on strlen of $collected_msg_num_string to determine if it has ONE DIGIT or not 1994 // but a single integer can be 1 char or 5 chars, for example, this causes *very* rare errors in the string groupings 1995 // causing not all message to be moved, or in the worst case, an error from the mailserver if a msgnum does not exist on it 1996 // whih can happen if 2 digits are put together without a comman or colon inbetween, makes a number unrelated to the grouping 1997 1998 if ($this->debug_wrapper_dcom_calls > 2) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): action required $grouped_move_balls DUMP', $grouped_move_balls); } 1999 // update this, this loop may have added to it since we last checked this 2000 $count_grouped = count($grouped_move_balls); 2001 $collected_msg_num_string = ''; 2002 // super dumb but simple way, just put a comma between all msgnum's 2003 //for ($group_loops=0; $group_loops < $count_grouped; $group_loops++) 2004 //{ 2005 // if ($group_loops > 0) 2006 // { 2007 // $collected_msg_num_string .= ','; 2008 // } 2009 // $collected_msg_num_string .= $grouped_move_balls[$group_loops]['mov_msgball']['msgnum']; 2010 //} 2011 // BETTER way, use rfv2060 specs to put range of msgnums together seperated by a colon 2012 for ($group_loops=0; $group_loops < $count_grouped; $group_loops++) 2013 { 2014 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * flush_buffered_move_commmands ('.__LINE__.'): loop ['.$group_loops.'] of ['.(string)($count_grouped-1).'], $collected_msg_num_string: ['.$collected_msg_num_string.']<br />'); } 2015 if ( ($group_loops > 0) 2016 //&& (($grouped_move_balls[$group_loops-1]['mov_msgball']['msgnum']+1) == $grouped_move_balls[$group_loops]['mov_msgball']['msgnum']) ) 2017 && ($grouped_move_balls[$group_loops-1]['mov_msgball']['msgnum']+1 == $grouped_move_balls[$group_loops]['mov_msgball']['msgnum']) ) 2018 { 2019 // we have a contiguous series, handle string specially 2020 if (($count_grouped == 2) 2021 && ($group_loops == 1)) 2022 { 2023 // two items will never make a series 2024 $collected_msg_num_string .= ','.(string)$grouped_move_balls[$group_loops]['mov_msgball']['msgnum']; 2025 } 2026 elseif ($group_loops == $count_grouped-1) 2027 { 2028 // the contiguous series of numbers just ended because the list is done 2029 // if there is not a comma nor a colon after the last number, put one there 2030 $last_char_idx = strlen((string)$collected_msg_num_string)-1; 2031 $last_char = $collected_msg_num_string[$last_char_idx]; 2032 // situation is that two contiguos numbers at the end of a list like this need a comma 2033 if (($last_char != ',') 2034 && ($last_char != ':')) 2035 { 2036 // COLON OR A COMMAN NEEDED 2037 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * flush_buffered_move_commmands ('.__LINE__.'): loop ['.$group_loops.'] of ['.(string)($count_grouped-1).'], COLON OR COMMA NEEDED: $last_char: ['.$last_char.'], $collected_msg_num_string: ['.$collected_msg_num_string.']<br />'); } 2038 if (($count_grouped > 2) 2039 //&& (strlen((string)$collected_msg_num_string) == 1)) 2040 && (!stristr($collected_msg_num_string, ':')) 2041 && (!stristr($collected_msg_num_string, ','))) 2042 { 2043 // ADD A COLON IF 2044 // (a) if the total things the move are > 2 AND 2045 // (b) there is so far only ONE number in our $collected_msg_num_string 2046 // then this is a series that had been uninterupted since it began looping here 2047 // situation is nums are 1, 2, 3, 4, 5, so in the last loop $collected_msg_num_string = "1:5" 2048 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * flush_buffered_move_commmands ('.__LINE__.'): loop ['.$group_loops.'] of ['.(string)($count_grouped-1).'], ADDING A COLON: $last_char: ['.$last_char.'], $collected_msg_num_string: ['.$collected_msg_num_string.']<br />'); } 2049 $collected_msg_num_string .= ':'; 2050 } 2051 else 2052 { 2053 // ADD A COMMA, these are 2054 // situation is nums are 3, 37, 38, so in the last loop $collected_msg_num_string = "3,37" 2055 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * flush_buffered_move_commmands ('.__LINE__.'): loop ['.$group_loops.'] of ['.(string)($count_grouped-1).'], ADDING A COMMA: $last_char: ['.$last_char.'], $collected_msg_num_string: ['.$collected_msg_num_string.']<br />'); } 2056 $collected_msg_num_string .= ','; 2057 } 2058 } 2059 $collected_msg_num_string .= (string)$grouped_move_balls[$group_loops]['mov_msgball']['msgnum']; 2060 } 2061 elseif ( (strlen($collected_msg_num_string) > 1) 2062 && ($collected_msg_num_string[strlen($collected_msg_num_string)-1] != ':') ) 2063 { 2064 // this is a contiguous series just starting, needs a colon 2065 $collected_msg_num_string .= ':'; 2066 } 2067 else 2068 { 2069 // DO NOTHING we are in the middle of this contiguous series of numbers 2070 } 2071 } 2072 // did a series just end? 2073 elseif ( ($group_loops > 1) 2074 && (($grouped_move_balls[$group_loops-2]['mov_msgball']['msgnum']+1) == $grouped_move_balls[$group_loops-1]['mov_msgball']['msgnum']) ) 2075 { 2076 // NOTE: ADD A COLON 2077 // if the previous existing $collected_msg_num_string does NOT have a colon or comma as its last crag 2078 $last_char_idx = strlen((string)$collected_msg_num_string)-1; 2079 $last_char = $collected_msg_num_string[$last_char_idx]; 2080 // situation is that the current end of a list needs something before we can add another number, (a comma or a colon) 2081 if (($last_char != ',') 2082 && ($last_char != ':')) 2083 { 2084 // so why colon and no check for a needed comma? 2085 // SINCE WE KNOW A SERIES JUST ENDED, whether just 2 contiguous numbers or 20 contiguous numbers 2086 // WE KNOW that a colon would be valid because we KNOW the previous existing number 2087 // AND the number we are about to add are IN A SERIES 2088 // so a colon would not create an unwanted series becuase we KNOW we have a series at this point 2089 // so ... a colon can not hurt, a colon between contiguous numbers is still valid syntax (i.e. "3:4" 2090 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * flush_buffered_move_commmands ('.__LINE__.'): loop ['.$group_loops.'] of ['.(string)($count_grouped-1).'], ADDING A COLON: $last_char: ['.$last_char.'], $collected_msg_num_string: ['.$collected_msg_num_string.']<br />'); } 2091 $collected_msg_num_string .= ':'; 2092 } 2093 // inset the number of the end of the series, a comman, and the current non-contiguous number 2094 $collected_msg_num_string .= 2095 (string)$grouped_move_balls[$group_loops-1]['mov_msgball']['msgnum'] 2096 .',' 2097 .(string)$grouped_move_balls[$group_loops]['mov_msgball']['msgnum']; 2098 } 2099 else 2100 { 2101 // we are NOT in a contiguous series, inset a comma, and the current number 2102 if (strlen((string)$collected_msg_num_string) > 0) 2103 { 2104 $collected_msg_num_string .= ','; 2105 } 2106 $collected_msg_num_string .= (string)$grouped_move_balls[$group_loops]['mov_msgball']['msgnum']; 2107 } 2108 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out(' * flush_buffered_move_commmands ('.__LINE__.'): $collected_msg_num_string: ['.$collected_msg_num_string.']<br />'); } 2109 } 2110 2111 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: final $collected_msg_num_string: ['.$collected_msg_num_string.']<br />'); } 2112 // 1b) issue the delete COMMAND finally now 2113 $mov_msgball = array(); 2114 $mov_msgball = $grouped_move_balls[$count_grouped-1]['mov_msgball']; 2115 $to_fldball = array(); 2116 $to_fldball = $grouped_move_balls[$count_grouped-1]['to_fldball']; 2117 // the FROM acctnum we'll use as "this_acctnum" 2118 $this_acctnum = $mov_msgball['acctnum']; 2119 // EXPIRE MSGBALL ???? wasn't this done with the notice of big move? 2120 // note since we ALWAYS turn off extreme caching when weuse this function, we *could* DIRECTLY expire it 2121 //if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): flush_buffered_move_commmands: expire msgball list with call to $this->event_msg_move_or_delete<br />'; } 2122 //$this->event_msg_move_or_delete($mov_msgball, 'flush_buffered_move_commmands'.' LINE: '.__LINE__.' and CACHE SHOULD BE OFF NOW', $to_fldball); 2123 //if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): flush_buffered_move_commmands: expire msgball list with DIRECT call to $this->expire_session_cache_item (because we know extreme caching os turned off for the duration of this function)<br />'; } 2124 //$this->expire_session_cache_item('msgball_list', $this_acctnum); 2125 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: ($do_it_for_real is '.serialize($do_it_for_real).'): calling $this->ensure_stream_and_folder($mov_msgball ['.serialize($mov_msgball).'], who_is_calling) <br />'); } 2126 if ($do_it_for_real == True) 2127 { 2128 $this->ensure_stream_and_folder($mov_msgball, 'flush_buffered_move_commmands'.' LINE: '.__LINE__); 2129 } 2130 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $this_acctnum); 2131 // IS THIS A MOVE OR A DELETE? 2132 if ($to_fldball['folder'] == $this->del_pseudo_folder || $to_fldball['folder'] == '##NOTHING##') 2133 { 2134 // STRAIGHT DELETE 2135 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: SRAIGHT DELETE ($do_it_for_real is '.serialize($do_it_for_real).'): $GLOBALS[phpgw_dcom_'.$this_acctnum.']->dcom->delete('.serialize($mailsvr_stream).' ,'.$collected_msg_num_string.')<br />'); } 2136 if ($do_it_for_real == True) 2137 { 2138 $did_delete = $GLOBALS['phpgw_dcom_'.$this_acctnum]->dcom->delete($mailsvr_stream , $collected_msg_num_string); 2139 if (!$did_delete) 2140 { 2141 $imap_err = $GLOBALS['phpgw_dcom_'.$this_acctnum]->dcom->server_last_error(); 2142 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: STRAIGHT DELETE: LEAVING on ERROR, $imap_err: ['.$imap_err.'] return False'.' LINE '.__LINE__.'<br />'); } 2143 echo 'mail_msg(_wrappers): flush_buffered_move_commmands: LEAVING on ERROR, $imap_err: ['.$imap_err.'] return False'.' LINE '.__LINE__.'<br />'; 2144 echo ' command was: $GLOBALS[phpgw_dcom_'.$this_acctnum.']->dcom->delete('.serialize($mailsvr_stream).' ,'.$collected_msg_num_string.')<br />'; 2145 return False; 2146 } 2147 } 2148 } 2149 else 2150 { 2151 // MOVE 2152 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: ($do_it_for_real is '.serialize($do_it_for_real).'): $GLOBALS[phpgw_dcom_'.$this_acctnum.']->dcom->mail_move('.serialize($mailsvr_stream).' ,'.$collected_msg_num_string.', '.serialize($to_fldball['folder']).')<br />'); } 2153 if ($do_it_for_real == True) 2154 { 2155 $did_move = $GLOBALS['phpgw_dcom_'.$this_acctnum]->dcom->mail_move($mailsvr_stream , $collected_msg_num_string, $to_fldball['folder']); 2156 if (!$did_move) 2157 { 2158 $imap_err = $GLOBALS['phpgw_dcom_'.$this_acctnum]->dcom->server_last_error(); 2159 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: LEAVING on ERROR, $imap_err: ['.$imap_err.'] return False'.' LINE '.__LINE__.'<br />'); } 2160 echo 'mail_msg(_wrappers): flush_buffered_move_commmands: LEAVING on ERROR, $imap_err: ['.$imap_err.'] return False'.' LINE '.__LINE__.'<br />'; 2161 echo ' command was: $GLOBALS[phpgw_dcom_'.$this_acctnum.']->dcom->mail_move('.serialize($mailsvr_stream).' ,'.$collected_msg_num_string.', '.serialize($to_fldball['folder']).')<br />'; 2162 return False; 2163 } 2164 } 2165 } 2166 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: LINE '.__LINE__.': is we get here we probably just issued a move or delete command, we may try to group more (usually only with filter usage) or we may be done with buffered command list<br />'); } 2167 } 2168 2169 // 2) if NOT the final item in $this->buffered_move_commmands we need to 2170 // 2a) then we need to clear grouped_move_balls and ADD this_move_balls to it to start a new grouping array 2171 // 2b) then run again thru the loop after that 2172 if ($x != $this->buffered_move_commmands_count-1) 2173 { 2174 $grouped_move_balls = array(); 2175 array_push($grouped_move_balls, $this_move_balls); 2176 // 3) then run again thru the loop after that 2177 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: continue; ... to look for groupable move commands for acctnum ['.$mailsvr_stream.']<br />'); } 2178 // doesn't this happen anyway here? 2179 continue; 2180 } 2181 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: still in that loop $x: ['.$x.'] $this->buffered_move_commmands_count-1: ['.(string)($this->buffered_move_commmands_count-1).'], if we get to here we SHOULD be done with all moves, else a continue would have been hit<br />'); } 2182 } 2183 2184 if ($is_big_move == True) 2185 { 2186 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands: $is_big_move: ['.serialize($is_big_move).'] we get to here we SHOULD be done so call $this->event_begin_big_end <br />'); } 2187 $this->event_begin_big_end('flush_buffered_move_commmands '.__LINE__); 2188 } 2189 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): flush_buffered_move_commmands ('.__LINE__.'): LEAVING<br />'); } 2190 // FIXME return something more useful 2191 return True; 2192 } 2193 2194 2195 /*! 2196 @function single_interacct_mail_move 2197 @abstract Primary mail move function for DIFFERENT Accounts. Moves single mails, use a loop if moving more than one mail. 2198 @param $mov_msgball (array of type msgball) the message the will be moved. 2199 @param $to_fldball (array of type fldball) the target of the move. 2200 @author Angles 2201 @discussion Can handle any kind of move, same account, different account, different server. Now 2202 used mostly for different account moves, because we attempt to group single account moves elsewhere. 2203 Fills arg "expunge_folders" for any account that has folders needing to be expunged. 2204 @access public 2205 */ 2206 function single_interacct_mail_move($mov_msgball='', $to_fldball='') 2207 { 2208 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: ENTERING (note: only feed ONE msgball at a time, i.e. NOT a list of msgballs) <br />'); } 2209 // Note: Only call this function with ONE msgball at a time, i.e. NOT a list of msgballs 2210 // INTERACCOUNT -OR- SAME ACCOUNT ? 2211 if ($this->debug_wrapper_dcom_calls > 2) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: $mov_msgball DUMP:', $mov_msgball); } 2212 if ($this->debug_wrapper_dcom_calls > 2) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: $to_fldball DUMP:', $to_fldball); } 2213 // --- Establist account numbers ---- 2214 $mov_msgball['acctnum'] = (int)$mov_msgball['acctnum']; 2215 if (!(isset($mov_msgball['acctnum'])) 2216 || ((string)$mov_msgball['acctnum'] == '')) 2217 { 2218 $mov_msgball['acctnum'] = $this->get_acctnum(); 2219 } 2220 $to_fldball['acctnum'] = (int)$to_fldball['acctnum']; 2221 if (!(isset($to_fldball['acctnum'])) 2222 || ((string)$to_fldball['acctnum'] == '')) 2223 { 2224 $to_fldball['acctnum'] = $this->get_acctnum(); 2225 } 2226 2227 // Are the acctnums the same? 2228 if ((string)$mov_msgball['acctnum'] == (string)$to_fldball['acctnum']) 2229 { 2230 // SAME ACCOUNT MAIL MOVE 2231 2232 $common_acctnum = $mov_msgball['acctnum']; 2233 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: SAME ACCOUNT MOVE $common_acctnum: '.$common_acctnum.' $mailsvr_stream: '.$mailsvr_stream.' $msgnum: '.$msgnum.' $mailsvr_callstr: '.$mailsvr_callstr.' $mailbox: '.$mailbox.'<br />'); } 2234 $this->event_msg_move_or_delete($mov_msgball, 'single_interacct_mail_move'.' LINE: '.__LINE__, $to_fldball); 2235 //$this->expire_session_cache_item('msgball_list', $common_acctnum); 2236 // we need to SELECT the folder the message is being moved FROM 2237 $mov_msgball['folder'] = urldecode($mov_msgball['folder']); 2238 2239 $this->ensure_stream_and_folder($mov_msgball, 'single_interacct_mail_move'.' LINE: '.__LINE__); 2240 $mov_msgball['msgnum'] = (string)$mov_msgball['msgnum']; 2241 $to_fldball['folder'] = urldecode($to_fldball['folder']); 2242 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $common_acctnum); 2243 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: $GLOBALS[phpgw_dcom_'.$common_acctnum.']->dcom->mail_move('.serialize($mailsvr_stream).' ,'.serialize($mov_msgball['msgnum']).', '.serialize($to_fldball['folder']).')<br />'); } 2244 $did_move = $GLOBALS['phpgw_dcom_'.$common_acctnum]->dcom->mail_move($mailsvr_stream ,$mov_msgball['msgnum'], $to_fldball['folder']); 2245 if (!$did_move) 2246 { 2247 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: LEAVING, return False'.' LINE '.__LINE__.'<br />'); } 2248 return False; 2249 } 2250 else 2251 { 2252 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move ('.__LINE__.'): SAME ACCOUNT MOVE *SUCCESS*, $did_move ['.serialize($did_move).'], now add this folder to this accounts "expunge_folders" arg via "track_expungable_folders"<br />'); } 2253 $this->track_expungable_folders($mov_msgball); 2254 //if ($this->debug_wrapper_dcom_calls > 0) { echo 'mail_msg(_wrappers): industrial_interacct_mail_move: LEAVING, about to call $this->phpgw_expunge('.$mov_msgball['acctnum'].')'.' LINE '.__LINE__.'<br />'; } 2255 //return $this->phpgw_expunge($mov_msgball['acctnum']); 2256 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move ('.__LINE__.'): LEAVING, returning True, SAME ACCOUNT MOVE SUCCESS (do not forget to expunge later) <br />'); } 2257 return True; 2258 } 2259 } 2260 else 2261 { 2262 // DIFFERENT ACCOUNT MAIL MOVE 2263 2264 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: Different ACCOUNT MOVE $common_acctnum: '.$common_acctnum.' $mailsvr_stream: '.$mailsvr_stream.' $msgnum: '.$msgnum.' $mailsvr_callstr: '.$mailsvr_callstr.' $mailbox: '.$mailbox.'<br />'); } 2265 $good_to_go = False; 2266 // delete session msg array data thAt is now stale 2267 $this->event_msg_move_or_delete($mov_msgball, 'single_interacct_mail_move'.' LINE: '.__LINE__, $to_fldball); 2268 //$this->expire_session_cache_item('msgball_list', $mov_msgball['acctnum']); 2269 $mov_msgball['folder'] = urldecode($mov_msgball['folder']); 2270 // Make Sure Stream Exists 2271 // multiple accounts means one stream may be open but another may not 2272 // "ensure_stream_and_folder" will verify for us, 2273 $this->ensure_stream_and_folder($mov_msgball, 'single_interacct_mail_move'); 2274 // GET MESSAGE FLAGS (before you get the mgs, so unseen/seen is not tainted by our grab) 2275 $hdr_envelope = $this->phpgw_header($mov_msgball); 2276 $mov_msgball['flags'] = $this->make_flags_str($hdr_envelope); 2277 // GET THE MESSAGE 2278 // part_no 0 only used to get the headers 2279 $mov_msgball['part_no'] = 0; 2280 // (a) the headers, specify part_no 0 2281 //$moving_message = $GLOBALS['phpgw']->msg->phpgw_fetchbody($mov_msgball); 2282 $moving_message = $this->phpgw_fetchbody($mov_msgball); 2283 // (b) the body, plus a CRLF, reuse headers_msgball b/c "phpgw_body" cares not about part_no 2284 //$moving_message .= $GLOBALS['phpgw']->msg->phpgw_body($mov_msgball)."\r\n"; 2285 $moving_message .= $this->phpgw_body($mov_msgball)."\r\n"; 2286 $good_to_go = (strlen($moving_message) > 3); 2287 if (!$good_to_go) 2288 { 2289 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: LEAVING, return False'.' LINE '.__LINE__.'<br />'); } 2290 return False; 2291 } 2292 2293 // APPEND TO TARGET FOLDER 2294 // delete session msg array data thAt is now stale 2295 // WE DO NOT GUESS ABOUT APPENDS, WE EXPIRE THE DATA AND GET FRESH 2296 //$this->expire_session_cache_item('msgball_list', $to_fldball['acctnum']); 2297 $this->event_msg_append($to_fldball, 'single_interacct_mail_move Line '.__LINE__); 2298 2299 2300 $to_fldball['folder'] = urldecode($to_fldball['folder']); 2301 // TEMP (MUST add this back!!!) append does NOT require we open the target folder, only requires a stream 2302 //$remember_to_fldball = $to_fldball['folder']; 2303 //$to_fldball['folder'] = ''; 2304 // PASS "no_switch_away" to indicate we should NOT CHANGE FOLDERS 2305 $to_fldball['no_switch_away'] = True; 2306 $this->ensure_stream_and_folder($to_fldball, 'single_interacct_mail_move'); 2307 $mailsvr_callstr = $this->get_arg_value('mailsvr_callstr', $to_fldball['acctnum']); 2308 $to_mailsvr_stream = $this->get_arg_value('mailsvr_stream', $to_fldball['acctnum']); 2309 //$to_fldball['folder'] = $remember_to_fldball; 2310 // $tol_folder_utldecoded = 2311 $good_to_go = $GLOBALS['phpgw_dcom_'.$to_fldball['acctnum']]->dcom->append($to_mailsvr_stream, $mailsvr_callstr.$to_fldball['folder'], $moving_message, $mov_msgball['flags']); 2312 if (!$good_to_go) 2313 { 2314 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: LEAVING, return False'.' LINE '.__LINE__.'<br />'); } 2315 return False; 2316 } 2317 // DELETE and EXPUNGE from FROM FOLDER 2318 $from_mailsvr_stream = $this->get_arg_value('mailsvr_stream', $mov_msgball['acctnum']); 2319 $good_to_go = $GLOBALS['phpgw_dcom_'.$mov_msgball['acctnum']]->dcom->delete($from_mailsvr_stream, $mov_msgball['msgnum']); 2320 if (!$good_to_go) 2321 { 2322 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: LEAVING, return False'.' LINE '.__LINE__.'<br />'); } 2323 return False; 2324 } 2325 //$good_to_go = $GLOBALS['phpgw']->msg->phpgw_expunge($mov_msgball['acctnum']); 2326 //$good_to_go = $this->phpgw_expunge($mov_msgball['acctnum']); 2327 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move ('.__LINE__.'): different account append and delete SUCCESS, now add this folder to this accounts "expunge_folders" arg via "track_expungable_folders"<br />'); } 2328 $this->track_expungable_folders($mov_msgball); 2329 2330 if (!$good_to_go) 2331 { 2332 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: LEAVING, return False'.' LINE '.__LINE__.'<br />'); } 2333 return False; 2334 } 2335 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): single_interacct_mail_move: LEAVING, return TRUE'.' LINE '.__LINE__.'<br />'); } 2336 return True; 2337 } 2338 } 2339 2340 /*! 2341 @function track_expungable_folders 2342 @abstract Keeps track of what accounts folders will need to be expunged. 2343 @author Angles 2344 @discussion Used by "industrial_interacct_mail_move" and "phpgw_delete" to keep track 2345 of which folders for any account will need to be expunged. NOTE this tracking occurs 2346 automatically in those functions, HOWEVER the calling function is responsible to 2347 call "expunge_expungable_folders" when all the moves or deletes are done. 2348 @access private 2349 */ 2350 function track_expungable_folders($fldball='') 2351 { 2352 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): track_expungable_folders ('.__LINE__.'): ENTERING, $fldball ['.serialize($fldball).']<br />'); } 2353 if (!(isset($fldball['acctnum'])) 2354 || ((string)$fldball['acctnum'] == '')) 2355 { 2356 $acctnum = $this->get_acctnum(); 2357 } 2358 else 2359 { 2360 $acctnum = $fldball['acctnum']; 2361 } 2362 if (!(isset($fldball['folder'])) 2363 || ((string)$fldball['folder'] == '')) 2364 { 2365 $folder = $this->get_arg_value('folder', $acctnum); 2366 } 2367 else 2368 { 2369 $folder = $fldball['folder']; 2370 } 2371 $my_fldball = array(); 2372 $my_fldball['folder'] = $folder; 2373 $my_fldball['acctnum'] = $acctnum; 2374 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): track_expungable_folders ('.__LINE__.'): $my_fldball ['.serialize($my_fldball).']<br />'); } 2375 2376 $first_addition_to_array = False; 2377 // get an array of folders that need expunging that we know of 2378 if ($this->get_isset_arg('expunge_folders', $my_fldball['acctnum']) == False) 2379 { 2380 $expunge_folders = array(); 2381 $first_addition_to_array = True; 2382 } 2383 else 2384 { 2385 //$expunge_folders = $this->get_arg_value('expunge_folders', $my_fldball['acctnum']); 2386 $expunge_folders =& $this->_get_arg_ref('expunge_folders', $my_fldball['acctnum']); 2387 } 2388 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): track_expungable_folders ('.__LINE__.'): $expunge_folders DUMP:', $expunge_folders); } 2389 // if this particular folder already in the array 2390 $loops = count($expunge_folders); 2391 $already_listed = False; 2392 for ($i=0; $i<$loops;$i++) 2393 { 2394 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): track_expungable_folders ('.__LINE__.'): loop ['.$i.'] of ['.$loops.'] $expunge_folders[$i] ['.htmlspecialchars($expunge_folders[$i]).'] same as $my_fldball[folder] ['.htmlspecialchars($my_fldball['folder']).'] test<br />'); } 2395 if ($expunge_folders[$i] == $my_fldball['folder']) 2396 { 2397 $already_listed = True; 2398 break; 2399 } 2400 } 2401 // if this folder was NOT already in the array, put it there and save the arg value 2402 if ($already_listed == False) 2403 { 2404 $new_idx = count($expunge_folders); 2405 $expunge_folders[$new_idx] = $my_fldball['folder']; 2406 if ($first_addition_to_array == True) 2407 { 2408 $this->set_arg_value('expunge_folders', $expunge_folders, $my_fldball['acctnum']); 2409 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): track_expungable_folders ('.__LINE__.'): LEAVING: added first item to $my_fldball[folder] ['.$my_fldball['folder'].'] to $expunge_folders ['.htmlspecialchars(serialize($expunge_folders)).']<br />'); } 2410 } 2411 else 2412 { 2413 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): track_expungable_folders ('.__LINE__.'): LEAVING: added VIA REFERENCE $my_fldball[folder] ['.$my_fldball['folder'].'] to $expunge_folders ['.htmlspecialchars(serialize($expunge_folders)).']<br />'); } 2414 } 2415 return True; 2416 } 2417 else 2418 { 2419 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): track_expungable_folders ('.__LINE__.'): LEAVING: $my_fldball[folder] ['.$my_fldball['folder'].'] was ALREADY in $expunge_folders ['.htmlspecialchars(serialize($expunge_folders)).']<br />'); } 2420 return False; 2421 } 2422 } 2423 2424 /*! 2425 @function expunge_expungable_folders 2426 @abstract loops thru ALL accounts, expunges any account that has folder names in its arg "expunge_folders" 2427 @author Angles 2428 @discussion This function uses the folder tracking from "track_expungable_folders" to know what 2429 to expunge. Call this function after all your moves or deletes are done. 2430 @access public 2431 */ 2432 function expunge_expungable_folders($called_by='not_specified') 2433 { 2434 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): expunge_expungable_folders ('.__LINE__.'): ENTERING, called by ['.$called_by.'], <br />'); } 2435 2436 $this->flush_buffered_move_commmands('expunge_expungable_folders'); 2437 2438 $expunge_folders = array(); 2439 for ($i=0; $i < count($this->extra_and_default_acounts); $i++) 2440 { 2441 if ($this->extra_and_default_acounts[$i]['status'] == 'enabled') 2442 { 2443 $this_acctnum = $this->extra_and_default_acounts[$i]['acctnum']; 2444 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): expunge_expungable_folders ('.__LINE__.'): acctnum ['.$this_acctnum.'] needs to be checked<br />'); } 2445 if ($this->get_isset_arg('expunge_folders', $this_acctnum) == True) 2446 { 2447 $expunge_folders = array(); 2448 $expunge_folders = $this->get_arg_value('expunge_folders', $this_acctnum); 2449 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): expunge_expungable_folders ('.__LINE__.'): acctnum ['.$this_acctnum.'] indicates these folder(s) need to be expunged, $expunge_folders DUMP:', $expunge_folders); } 2450 2451 for ($x=0; $x < count($expunge_folders); $x++) 2452 { 2453 $success = False; 2454 $fake_fldball = array(); 2455 $fake_fldball['acctnum'] = $i; 2456 $fake_fldball['folder'] = $expunge_folders[$x]; 2457 $success = $this->phpgw_expunge('', $fake_fldball); 2458 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): expunge_expungable_folders ('.__LINE__.'): expunge for $fake_fldball ['.htmlspecialchars(serialize($fake_fldball)).'] returns ['.serialize($success).']<br />'); } 2459 } 2460 // we are done with this account, we expunged all expungable folders, not UNSET that arg so it is not left hanging around 2461 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): expunge_expungable_folders ('.__LINE__.'): finished expunging folders for acctnum ['.$this_acctnum.'] , now issue: $this->unset_arg("expunge_folders", '.$this_acctnum.') <br />'); } 2462 $this->unset_arg('expunge_folders', $this_acctnum); 2463 } 2464 else 2465 { 2466 $expunge_folders = array(); 2467 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): expunge_expungable_folders ('.__LINE__.'): acctnum ['.$this_acctnum.'] has NO value for "expunge_folders"<br />'); } 2468 } 2469 } 2470 } 2471 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): expunge_expungable_folders ('.__LINE__.'): LEAVING<br />'); } 2472 // FIXME return something more useful 2473 return True; 2474 } 2475 2476 2477 /*! 2478 @function phpgw_expunge 2479 @abstract Expunge a folder. 2480 @author Angles 2481 @discussion Brainless function, used by "expunge_expungable_folders" which is a "smart" 2482 function. This may be called directly, but it is preferable to use "expunge_expungable_folders" 2483 assuming the move or delete function you used calls "track_expungable_folders". 2484 @access public 2485 */ 2486 function phpgw_expunge($acctnum='', $fldball='') 2487 { 2488 if (!(isset($acctnum)) 2489 || ((string)$acctnum == '')) 2490 { 2491 if (!(isset($fldball['acctnum'])) 2492 || ((string)$fldball['acctnum'] == '')) 2493 { 2494 $acctnum = $this->get_acctnum(); 2495 } 2496 else 2497 { 2498 $acctnum = $fldball['acctnum']; 2499 } 2500 } 2501 2502 //$fake_fldball = array(); 2503 //$fake_fldball['folder'] = $this->get_arg_value('folder', $acctnum); 2504 2505 // NOTE: it is OK to pass blank folder to "ensure_stream_and_folder" when FOLDER DOE NOT MATTER 2506 // for expunge, all we need is a stream, 2507 //$fake_fldball['acctnum'] = $acctnum; 2508 //$this->ensure_stream_and_folder($fake_fldball, 'phpgw_expunge'.' LINE '.__LINE__); 2509 // NOTE THAT CAUSED MAILSERVER TO REOPEN *AWAY* FROM FOLDER NEEDING EXPUNGE 2510 // and re-open to INBOX because a blank folder arg was passed. 2511 if ((isset($fldball['acctnum'])) 2512 && ((string)$fldball['acctnum'] != '') 2513 && (isset($fldball['folder'])) 2514 && ((string)$fldball['folder'] != '')) 2515 { 2516 $this->ensure_stream_and_folder($fldball, 'phpgw_expunge'.' LINE '.__LINE__); 2517 } 2518 2519 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 2520 $note_folder = $this->get_arg_value('folder', $acctnum); 2521 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): dcom_call: phpgw_expunge: $acctnum: '.serialize($acctnum).' NOTE current "folder" arg set for that acct is ['.$note_folder.']<br />'); } 2522 2523 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): dcom_call: phpgw_expunge: $acctnum: '.serialize($acctnum).' $mailsvr_stream: '.$mailsvr_stream.'<br />'); } 2524 return $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->expunge($mailsvr_stream); 2525 } 2526 2527 /*! 2528 @function phpgw_delete 2529 @abstract Delete a message, will move to "Trash" folder is necessary. 2530 @author Angles 2531 @param $msg_num (int) single msgnum of msg to "delete" (or move to trash folder") 2532 @param $currentfolder (string) full name (as in folder_long) and urlencoded name of the 2533 folder from which we are deleting from. 2534 @param $acctnum (int) (optional) acctnum this applies to 2535 @param $known_single_delete (boolean) BEING PHASED OUT was used to take abreviated action 2536 if we know this is only a single delete, not just one in a series, this logic being moved elsewhere. 2537 @discussion If the user pref wants to use the Trash folder, this function will auto-create 2538 that folder if it does not already exist, and move the mail to that trash folder. If 2539 the user pref is to not use a trash folder, or if deleting mail that is IN the trash folder, 2540 then a straight delete is done. Keeps track of folders needing expunging via calls 2541 to "track_expungable_folders", but the calling process is responsible to 2542 call "expunge_expungable_folders" after all deletes have been done. 2543 @access public 2544 */ 2545 function phpgw_delete($msg_num,$flags=0, $currentfolder="", $acctnum='', $known_single_delete=False) 2546 { 2547 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete: ENTERING <br />'); } 2548 2549 if (!(isset($acctnum)) 2550 || ((string)$acctnum == '')) 2551 { 2552 $acctnum = $this->get_acctnum(); 2553 } 2554 // everything from now on MUST specify this $acctnum 2555 2556 // now get the stream that applies to that acctnum 2557 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete: $acctnum: ['.$acctnum.'], $msg_num: ['.$msg_num.']<br />'); } 2558 2559 // this get arg value checks the pref for enabled or not enabled, no need to do it again 2560 if ($this->get_isset_arg('verified_trash_folder_long', $acctnum) == False) 2561 { 2562 $trash_folder_primer = $this->get_arg_value('verified_trash_folder_long', $acctnum); 2563 $trash_folder_primer = ''; 2564 unset($trash_folder_primer); 2565 } 2566 2567 // -- determine if we are moving to the trash folder or actually deleting the message 2568 $trash_folder_long =& $this->_get_arg_ref('verified_trash_folder_long', $acctnum); 2569 // if $trash_folder_long is not an ampty string, we need to try to move msgs to it 2570 if ($trash_folder_long != '') 2571 { 2572 // get a clean version 2573 $currentfolder_encoded = $currentfolder; 2574 $currentfolder_clean = urldecode($currentfolder); 2575 2576 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): "Trash" folder pref is enabled, does $currentfolder_clean ['.htmlspecialchars($currentfolder_clean).'] equal $trash_folder_long ['.htmlspecialchars($trash_folder_long).'] <br />'); } 2577 //echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): "Trash" folder pref is enabled, does ['.$currentfolder.'] == ['.$trash_folder_long.']<br />'; 2578 if ( ($currentfolder_clean != '') 2579 && ($currentfolder_clean == $trash_folder_long) ) 2580 { 2581 $straight_delete = True; 2582 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): "Trash" folder pref is enabled, YES to does $currentfolder_clean ['.htmlspecialchars($currentfolder_clean).'] equal $trash_folder_long ['.htmlspecialchars($trash_folder_long).'] <br />'); } 2583 //echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): "Trash" folder pref is enabled, shortcut good<br />'; 2584 } 2585 else 2586 { 2587 $straight_delete = False; 2588 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): "Trash" folder pref is enabled, NO to does $currentfolder_clean ['.htmlspecialchars($currentfolder_clean).'] equal $trash_folder_long ['.htmlspecialchars($trash_folder_long).'] <br />'); } 2589 } 2590 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): $straight_delete: ['.serialize($straight_delete).'], $currentfolder_clean: ['.htmlspecialchars($currentfolder_clean).'] $trash_folder_long: ['.htmlspecialchars($trash_folder_long).'] <br />'); } 2591 } 2592 else 2593 { 2594 $straight_delete = True; 2595 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): $straight_delete: ['.serialize($straight_delete).'] because $trash_folder_long ['.htmlspecialchars($trash_folder_long).'] is empty string<br />'); } 2596 } 2597 2598 // now that we know if this is a straight delete or not 2599 // TAKE ACTION 2600 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): taking action based on info that $straight_delete: ['.serialize($straight_delete).']<br />'); } 2601 if ($straight_delete == True) 2602 { 2603 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): begin code for STRAIGHT DELETE<br />'); } 2604 $mov_msgball = array(); 2605 if ((isset($currentfolder_encoded)) 2606 && ((string)$currentfolder_encoded != '')) 2607 { 2608 // lets trust that current folder is in long form 2609 $mov_msgball['folder'] = $currentfolder_encoded; 2610 } 2611 else 2612 { 2613 $mov_msgball['folder'] = $this->prep_folder_out(); 2614 } 2615 $mov_msgball['acctnum'] = $acctnum; 2616 $mov_msgball['msgnum'] = $msg_num; 2617 2618 // STRAIGHT DELETE has a "PSUEDO FOLDER" called "##DELETE##" 2619 // that we use in the "flush_buffered_move_commmands" to indicate a delete instead of a move 2620 // AND we'll use the same "acctnum" as the delete from acctnum because this will group them together during a "sort" of the array 2621 // so we can use the same function for both 2622 $to_fldball = array(); 2623 $to_fldball['acctnum'] = $mov_msgball['acctnum']; 2624 $to_fldball['folder'] = $this->del_pseudo_folder; 2625 2626 // PUT THIS COMMAND IN THE BUFFERED MOVE (OR DELETE) ARRAY 2627 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): STRAIGHT DELETE: calling $this->industrial_interacct_mail_move($mov_msgball['.serialize($mov_msgball).'],$to_fldball['.serialize($to_fldball).']) <br />'); } 2628 $did_take_action = $this->industrial_interacct_mail_move($mov_msgball, $to_fldball); 2629 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): LEAVING, returning $did_take_action ['.serialize($did_take_action).'] (does not really mean anything since we buffer the command) DO NOT FORGET TO EXPUNGE LATER<br />'); } 2630 // LEAVING 2631 return $did_take_action; 2632 2633 /* 2634 // BELOW HERE SHOULD GO INTO THE NEW STRAIGHT DELETE BUFFER 2635 if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): calling $this->event_msg_move_or_delete()<br />'; } 2636 $this->event_msg_move_or_delete($mov_msgball, 'phpgw_delete'.' LINE: '.__LINE__); 2637 //$this->expire_session_cache_item('msgball_list', $acctnum); 2638 // delete this when we start buffering straight deletes 2639 if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): calling $this->ensure_stream_and_folder()<br />'; } 2640 $this->ensure_stream_and_folder($mov_msgball, 'phpgw_delete'.' LINE '.__LINE__); 2641 2642 if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): getting "mailsvr_stream"<br />'; } 2643 $mailsvr_stream = $this->get_arg_value('mailsvr_stream', $acctnum); 2644 //return imap_delete($mailsvr_stream,$msg_num); 2645 if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): calling GLOBALS[phpgw_dcom_'.$acctnum.']->dcom->delete('.serialize($mailsvr_stream).', '.serialize($msg_num).') <br />'; } 2646 $retval = $GLOBALS['phpgw_dcom_'.$acctnum]->dcom->delete($mailsvr_stream, $msg_num); 2647 if ($retval) 2648 { 2649 if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): phpgw_delete ('.__LINE__.'): delete *SUCCESS*, now add this folder to this accounts "expunge_folders" arg via "track_expungable_folders"<br />'; } 2650 $this->track_expungable_folders($mov_msgball); 2651 } 2652 if ($this->debug_wrapper_dcom_calls > 0) { echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): EXITING with $retval ['.serialize($retval).'] DO NOT FORGET TO EXPUNGE LATER<br />'; } 2653 // LEAVING 2654 return $retval; 2655 */ 2656 } 2657 else 2658 { 2659 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): begin do move to trash folder<br />'); } 2660 $mov_msgball = array(); 2661 if ((isset($currentfolder_encoded)) 2662 && ((string)$currentfolder_encoded != '')) 2663 { 2664 // lets trust that current folder is in long form (and encoded - I guess we like it that way? it came in here that way) 2665 $mov_msgball['folder'] = $currentfolder_encoded; 2666 } 2667 else 2668 { 2669 $mov_msgball['folder'] = $this->prep_folder_out(); 2670 } 2671 $mov_msgball['acctnum'] = $acctnum; 2672 $mov_msgball['msgnum'] = $msg_num; 2673 // destination Trash Folder 2674 $to_fldball = array(); 2675 $to_fldball['folder'] = $trash_folder_long; 2676 $to_fldball['acctnum'] = $acctnum; 2677 // this event MOVED to flush command 2678 //if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): calling $this->event_msg_move_or_delete<br />'; } 2679 //$this->event_msg_move_or_delete($mov_msgball, 'phpgw_delete'.' LINE: '.__LINE__, $to_fldball); 2680 //$this->expire_session_cache_item('msgball_list', $acctnum); 2681 2682 //if ($known_single_delete == True) 2683 //{ 2684 // // we were told this is just a SINGLE delete call, NOT multiple deletes involved 2685 // if ($this->debug_wrapper_dcom_calls > 1) { echo 'mail_msg(_wrappers): phpgw_delete('.__LINE__.'): $known_single_delete: ['.serialize($known_single_delete).'] so calling $this->single_interacct_mail_move($mov_msgball['.serialize($mov_msgball).'],$to_fldball['.serialize($to_fldball).']) <br />'; } 2686 // $did_move = $this->single_interacct_mail_move($mov_msgball, $to_fldball); 2687 //} 2688 //else 2689 //{ 2690 // most (WAS) likely multiple deletes, so use the command that buffers the moves 2691 // this logic concerning single or not has been moved elsewhere 2692 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): $known_single_delete: ['.serialize($known_single_delete).'] so calling $this->industrial_interacct_mail_move($mov_msgball['.serialize($mov_msgball).'],$to_fldball['.serialize($to_fldball).']) <br />'); } 2693 $did_move = $this->industrial_interacct_mail_move($mov_msgball, $to_fldball); 2694 //} 2695 if ($this->debug_wrapper_dcom_calls > 1) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete('.__LINE__.'): $did_move: ['.serialize($did_move).'], does not mean unless you called $this->single_interacct_mail_move()<br />'); } 2696 2697 if ($this->debug_wrapper_dcom_calls > 0) { $this->dbug->out('mail_msg(_wrappers): phpgw_delete ('.__LINE__.'): LEAVING, returning $did_move ['.serialize($did_move).'] DO NOT FORGET TO EXPUNGE LATER<br />'); } 2698 return $did_move; 2699 } 2700 } 2701 2702 2703 /*! 2704 @function get_verified_trash_folder_long 2705 @abstract SPECIAL HANDLER for use by "get_arg_value" for "verified_trash_folder_long" 2706 @param (int) the account number OPTIONAL if not supplied current acctnum is used 2707 @result (string) folder long name of trash folder, or empty string on failure 2708 @discussion First there is a pref called "trash_folder_name" that needs some processing 2709 because .1. the name is stored in user friendly form, is not known to be authentic server 2710 string folder long style, and .2. if the folder does not yet exist we must make it. This function 2711 does that processing, the result of this is put into arg value "verified_trash_folder_long". So 2712 if you need to know about the trash folder, use get_arg_value("verified_trash_folder_long") and 2713 this is all transparent to you. **CACHE NOTE** this value is stored in LEVEL 1 temporary cache 2714 for the duration of the script run, perhaps later we could put in appsession cache but if so then it 2715 must be expired if new prefs are submited. 2716 @author Angles 2717 */ 2718 function get_verified_trash_folder_long($acctnum='') 2719 { 2720 if ($this->debug_args_special_handlers > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: ENTERING<br />'); } 2721 2722 if ((!isset($acctnum)) 2723 || ((string)$acctnum == '')) 2724 { 2725 $acctnum = $this->get_acctnum(); 2726 } 2727 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg: get_verified_trash_folder_long('.__LINE__.'): after testing feed arg, using $acctnum: ['.$acctnum.']<br />'); } 2728 2729 // L1 (temporary) CACHED data available ? 2730 $class_cached_verified_trash_folder_long = $this->_direct_access_arg_value('verified_trash_folder_long', $acctnum); 2731 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg: get_verified_trash_folder_long('.__LINE__.'): check for L1 class var cached data: $this->_direct_access_arg_value(verified_trash_folder_long, '.$acctnum.'); returns: '.serialize($class_cached_verified_trash_folder_long).'<br />'); } 2732 if ((isset($class_cached_verified_trash_folder_long)) 2733 && ($class_cached_verified_trash_folder_long != '')) 2734 { 2735 // return the cached data 2736 if ($this->debug_args_special_handlers > 0) { $this->dbug->out('mail_msg: get_verified_trash_folder_long('.__LINE__.'): LEAVING, returned class var cached data: '.serialize($class_cached_verified_trash_folder_long).'<br />'); } 2737 return $class_cached_verified_trash_folder_long; 2738 } 2739 // NO CACHED data, continue ... 2740 2741 // does the mailserver have folders, if not then there is NO trash folder no matter what 2742 if ($this->get_mailsvr_supports_folders($acctnum) == False) 2743 { 2744 if ($this->debug_args_special_handlers > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: LEAVING, mailserver does NOT support folders, so storing and returning empty string<br />'); } 2745 // exit, trash folder pref is NOT TO USE ONE, so we certainly do not have a "verified" name in this case 2746 $this->set_arg_value('verified_trash_folder_long', '', $acctnum); 2747 return ''; 2748 } 2749 2750 // are we even supposed to use a trash folder 2751 if ( (!$this->get_isset_pref('use_trash_folder', $acctnum)) 2752 || (!$this->get_pref_value('use_trash_folder', $acctnum)) ) 2753 { 2754 if ($this->debug_args_special_handlers > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: LEAVING, user does NOT prefer to use a trash folder, so storing and returning empty string<br />'); } 2755 // exit, trash folder pref is NOT TO USE ONE, so we certainly do not have a "verified" name in this case 2756 $this->set_arg_value('verified_trash_folder_long', '', $acctnum); 2757 return ''; 2758 } 2759 2760 // does the trash folder actually exist ? 2761 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: humm... does the "Trash" folder actually exist :: this->get_pref_value("trash_folder_name", '.$acctnum.') = ['.htmlspecialchars($this->get_pref_value('trash_folder_name', $acctnum)).']<br />'); } 2762 $verified_trash_folder_long = $this->folder_lookup('', $this->get_pref_value('trash_folder_name', $acctnum)); 2763 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: did lookup on pref value for "Trash" folder, got $verified_trash_folder_long ['.htmlspecialchars($verified_trash_folder_long).']<br />'); } 2764 if ((isset($verified_trash_folder_long)) 2765 && ($verified_trash_folder_long != '')) 2766 { 2767 $havefolder = True; 2768 } 2769 else 2770 { 2771 $havefolder = False; 2772 } 2773 2774 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: "Trash" folder $havefolder so far is ['.serialize($havefolder).']<br />'); } 2775 2776 if (!$havefolder) 2777 { 2778 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: we have to create the "Trash" folder so it will exist<br />'); } 2779 // create the Trash folder so it will exist (Netscape does this too) 2780 //$mailsvr_callstr = $this->get_arg_value('mailsvr_callstr', $acctnum); 2781 $namespace = $this->get_arg_value('mailsvr_namespace', $acctnum); 2782 $delimiter = $this->get_arg_value('mailsvr_delimiter', $acctnum); 2783 $make_this_folder_clean = $namespace.$delimiter.$this->get_pref_value('trash_folder_name', $acctnum); 2784 $make_this_folder_encoded = $this->prep_folder_out($make_this_folder_clean); 2785 //$this->createmailbox($mailsvr_stream,$server_str .$trash_folder_long); 2786 //$this->phpgw_createmailbox("$server_str"."$trash_folder_long"); 2787 $fake_fldball = array(); 2788 $fake_fldball['folder'] = $make_this_folder_encoded; 2789 $fake_fldball['acctnum'] = $acctnum; 2790 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: calling $this->phpgw_createmailbox_ex('.serialize($fake_fldball).') <br />'); } 2791 //$did_create = $this->phpgw_createmailbox($fake_fldball); 2792 $did_create = $this->phpgw_createmailbox_ex($fake_fldball); 2793 if (!$did_create) 2794 { 2795 $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: UNABLE TO CREATE ['.htmlspecialchars(serialize($fake_fldball)).']'); 2796 echo 'mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: UNABLE TO CREATE ['.htmlspecialchars(serialize($fake_fldball)).']'; 2797 } 2798 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: phpgw_createmailbox returns $did_create ['.serialize($did_create ).'] <br />'); } 2799 2800 // try again to get the real long folder name of the just created trash folder 2801 $verified_trash_folder_long = $this->folder_lookup('', $this->get_pref_value('trash_folder_name', $acctnum)); 2802 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: Another lookup on pref value for "Trash" folder, got $verified_trash_folder_long ['.htmlspecialchars($verified_trash_folder_long).']<br />'); } 2803 // did the folder get created and do we now have the official full name of that folder? 2804 if ($verified_trash_folder_long != '') 2805 { 2806 $havefolder = True; 2807 } 2808 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): get_verified_trash_folder_long: Another check of "Trash" folder $havefolder so far is ['.serialize($havefolder).']<br />'); } 2809 } 2810 2811 if ($havefolder == False) 2812 { 2813 // FAILED to find or make trash folder, return empty string 2814 $verified_trash_folder_long = ''; 2815 } 2816 else 2817 { 2818 // SUCCESS, put the result in L1 (page view only) cache 2819 // cache the result in "level one cache" class var holder 2820 if ($this->debug_args_special_handlers > 1) { $this->dbug->out('mail_msg: get_verified_trash_folder_long('.__LINE__.'): set "level 1 cache, class var" arg $this->set_arg_value(verified_trash_folder_long, '.$verified_trash_folder_long.', '.$acctnum.']) <br />'); } 2821 $this->set_arg_value('verified_trash_folder_long', $verified_trash_folder_long, $acctnum); 2822 // LATER put it in appsession cache BUT make code to delete it from cache when submitting new prefs 2823 } 2824 if ($this->debug_args_special_handlers > 0) { $this->dbug->out('mail_msg(_wrappers): get_verified_trash_folder_long('.__LINE__.'): LEAVING, returning $verified_trash_folder_long ['.serialize($verified_trash_folder_long).']<br />'); } 2825 return $verified_trash_folder_long; 2826 } 2827 2828 /**************************************************************************\ 2829 * END DCOM WRAPERS * 2830 * - - - - - - - - - - - - - - - - - - - - - - - - - * 2831 * BEGIN INPUT ARG/PARAM HANDLERS * 2832 \**************************************************************************/ 2833 2834 /*! 2835 @function is_ball_data 2836 @abstract Quick test an array to see if has the elements a fldball needs to be considered a fldball, 2837 or a msgball has the minumum elements to be a msgball. 2838 @param $maybe_ball (array of type fldball or msgball) OR string of URI type representation of a fldball 2839 or msgabll array, depends on the next param. This data is what we test this to see if it is ball data. 2840 @param $expect_ball_type (known string) either "fldball" or "msgball" or "any" what we expect the 2841 inpout data is supposed to be. Test above param to see if it is either a fldball or a msgball as we 2842 specify here. Value of "any" means do not do strict test, just a general test meeting fldball 2843 minimum criteria, but it could also be a msgball and still produce a True result. 2844 @param $is_uri_type_string (boolean) default is False, set to true if the above param is not an 2845 array but is known to be in URI string form. To test accurately this param is needed. 2846 NOTE that the test on this param is empty is the same as False and not empty is the same as True. 2847 However empty does not mean "not set", in other words an empty string is still something that 2848 "is set", it does exist as a data item. 2849 @result Boolean True if param tests OK for being a fldball, False otherwise. 2850 @discussion Pass an ARRAY into here unless you pass the second param as True, then 2851 you must pass string URI representation of a fldball. 2852 BACKGROUND there are 2 ways we hold fldball (and msgball) 2853 data, they are similar and can convert between one another. First is the actual associative array that 2854 has the elements needed to make a fldball, at a minimum "acctnum" and "folder". Second is a 2855 URI type string that is the URI representation of that array, such that is passed in a GET uri 2856 which php would translate into an array. This function expects the array form. NOTE that 2857 the php parse_str command will always add ot strip slashes during this conversion, als GPC magic_quotes, 2858 no matter what the setting for magic quotes is set to. Remember this because that can change the 2859 folder name into something with additional slashes in some cases. 2860 @author Angles 2861 @access Public 2862 */ 2863 function is_ball_data($maybe_ball='##NOTHING##', $expect_ball_type='any', $is_uri_type_string='') 2864 { 2865 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): ENTERING<br />'); } 2866 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): param $maybe_ball ['.htmlspecialchars(serialize($maybe_ball)).'], param $expect_ball_type ['.$expect_ball_type.'], param $is_uri_type_string ['.htmlspecialchars(serialize($is_uri_type_string)).'] <br />'); } 2867 // sanity check on input data 2868 if ((!isset($maybe_ball)) 2869 || ($maybe_ball == $this->nothing) 2870 || (!isset($expect_ball_type)) 2871 || (!isset($is_uri_type_string))) 2872 { 2873 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): LEAVING with error, input params error, returning False <br />'); } 2874 return False; 2875 } 2876 elseif (($expect_ball_type != 'fldball') 2877 && ($expect_ball_type != 'msgball') 2878 && ($expect_ball_type != 'any')) 2879 { 2880 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): LEAVING with error, param $expect_ball_type ['.htmlspecialchars(serialize($expect_ball_type)).'], is neither "fldball" nor "msgball" nor "any" , returning False <br />'); } 2881 return False; 2882 } 2883 // baseline data 2884 $test_results = array(); 2885 $test_results['verified_is_fldball'] = False; 2886 $test_results['verified_is_msgball'] = False; 2887 $test_results['final_verdict'] = False; 2888 // convert to array if necessary 2889 if ($is_uri_type_string) 2890 { 2891 $maybe_ball_uri = $maybe_ball; 2892 $maybe_ball = $this->ball_data_parse_str($maybe_ball_uri); 2893 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): needed to converted $maybe_ball_uri ['.htmlspecialchars(serialize($maybe_ball_uri)).'] to ball data array $maybe_ball ['.htmlspecialchars(serialize($maybe_ball)).'] <br />'); } 2894 } 2895 // easiest test, is it a fldball 2896 if ((isset($maybe_ball['folder'])) 2897 && ((string)$maybe_ball['folder'] != '') 2898 && (isset($maybe_ball['acctnum'])) 2899 && ((string)$maybe_ball['acctnum'] != '')) 2900 { 2901 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): input data DOES have minimun data of a FLDBALL, so generically it is "ball data", but also do the "msgnum" test, we may need it later. <br />'); } 2902 $test_results['verified_is_fldball'] = True; 2903 } 2904 2905 // additional test for msgball type ball data 2906 // only need to test this if the fldball criteria were met, if not it certainly can not be a msgball 2907 if (($test_results['verified_is_fldball'] == True) 2908 && (isset($maybe_ball['msgnum'])) 2909 && ((string)$maybe_ball['msgnum'] != '')) 2910 { 2911 $test_results['verified_is_msgball'] = True; 2912 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): input data is a MSGBALL, so it is not a FLDBALL, but is "ball data" in the generic sence<br />'); } 2913 } 2914 //make a determination 2915 if (($expect_ball_type == 'any') 2916 && ($test_results['verified_is_fldball'] == True)) 2917 { 2918 // testing for "any" type of ball data is True if minimal criteria of fldball are met 2919 $test_results['final_verdict'] = True; 2920 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): testing for '.$expect_ball_type.' data and input data meets minimum criteria for FLDBALL<br />'); } 2921 } 2922 elseif (($expect_ball_type == 'fldball') 2923 && ($test_results['verified_is_fldball'] == True) 2924 && ($test_results['verified_is_msgball'] == False)) 2925 { 2926 // strictly speaking, data is NOT a fldball if it ALSO has a msgnum, if using a strict match, not "any" ball 2927 // if the data ALSO HAS a msgnum, is is NOT a fldball, it is a msgball in the strict sence. 2928 $test_results['final_verdict'] = True; 2929 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): expected a '.$expect_ball_type.' and input data is a FLDBALL, and dod NOT have msgball element(s) <br />'); } 2930 } 2931 elseif (($expect_ball_type == 'msgball') 2932 && ($test_results['verified_is_fldball'] == True) 2933 && ($test_results['verified_is_msgball'] == True)) 2934 { 2935 $test_results['final_verdict'] = True; 2936 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): expected a '.$expect_ball_type.' and input data is a MSGBALL<br />'); } 2937 } 2938 else 2939 { 2940 $test_results['final_verdict'] = False; 2941 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): expected a '.$expect_ball_type.' but input data does not match that or is not ball data at all.<br />'); } 2942 } 2943 // return the result 2944 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: is_ball_data('.__LINE__.'): LEAVING, returning $test_results[final_verdict] of ['.htmlspecialchars(serialize($test_results['final_verdict'])).']<br />'); } 2945 return $test_results['final_verdict']; 2946 } 2947 2948 /*! 2949 @function ball_data_parse_str 2950 @abstract used for fldball and msgball data, apply php command parse string then apply stripslashes on folder names. 2951 @param $uri_ball_data (str) string in the style of a URI such as "msgball[msgnum]=2&msgball[folder]=INBOX&msgball[acctnum]=5" 2952 @param $do_stripslashes boolean default is True, whether to apply stripslashes to folder values, extremely rare to change this 2953 @result associative array of type msgball or fldball, which ever was fed as param $uri_type_string 2954 @discussion php command parse_str will ALWAYS add slashes to single and double quotes, just like GPC magic quotes 2955 except that even if you disable GPC magic quotes, parse_str will STILL add that escape slash to any quotes. This means 2956 that folder names in URI type data that we wish to decode with parse_str will ALSO need to be stripslashed 2957 or else any folder names with quotes in the, which is legal as per RFC 2060, suh folder names will not match 2958 our known list of folder names because these slashes will have been added to the folder name, if it contains quotes. 2959 Therefor this function is designed to decode fldball and msgball data and also stripslash the folder names that 2960 this function can find. USE FOR FLDBALL AND MSGBALL DATA ONLY because this function only looks 2961 for folder names where they would exist in a fldball or magball array, IT WILL NOT stripslash foldernames 2962 of any other type of data because it does not look for the folder name anywhere else. 2963 @author Angles 2964 @access Public 2965 */ 2966 function ball_data_parse_str($uri_ball_data='', $do_stripslashes=True) 2967 { 2968 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: ball_data_parse_str('.__LINE__.'): ENTERING<br />'); } 2969 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: ball_data_parse_str('.__LINE__.'): param $uri_ball_data ['.$uri_ball_data.']<br />'); } 2970 $return_struct = array(); 2971 if (!$uri_ball_data) 2972 { 2973 return $return_struct; 2974 } 2975 parse_str($uri_ball_data, $return_struct); 2976 // RAISE UP one level, we want the return to be the msgball or fldball itself 2977 if (stristr($uri_ball_data,'fldball[folder]')) 2978 { 2979 $return_struct = $return_struct['fldball']; 2980 } 2981 elseif (stristr($uri_ball_data,'msgball[folder]')) 2982 { 2983 $return_struct = $return_struct['msgball']; 2984 } 2985 else 2986 { 2987 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: ball_data_parse_str('.__LINE__.'): UNHANDLED and unexpected if .. then data <br />'); } 2988 } 2989 // add to this data a "uri" element that is the $uri_ball_data 2990 //if (isset($return_struct['uri']) == False) 2991 //{ 2992 //$return_struct['uri'] = $uri_ball_data; 2993 //} 2994 if ($do_stripslashes == True) 2995 { 2996 // this function is DUMB it only looks here for a folder name 2997 if (isset($return_struct['folder'])) 2998 { 2999 $return_struct['folder'] = stripslashes($return_struct['folder']); 3000 } 3001 } 3002 // we always keep folder data in urlencoded form until the last second 3003 $return_struct['folder'] = $this->prep_folder_out($return_struct['folder']); 3004 //rebuild the uri string 3005 $return_struct['uri'] = 'msgball[msgnum]='.$return_struct['msgnum'].'&msgball[folder]='.$return_struct['folder'].'&msgball[acctnum]='.$return_struct['acctnum']; 3006 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: ball_data_parse_str('.__LINE__.'): final $return_struct DUMP:', $return_struct); } 3007 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: ball_data_parse_str('.__LINE__.'): LEAVING<br />'); } 3008 return $return_struct; 3009 } 3010 3011 /*! 3012 @function decode_fake_uri 3013 @abstract decodes a URI type "query string" into an associative array 3014 @param $uri_type_string string in the style of a URI such as "&item=phone&action=dial" 3015 @result associative array where the $key and $value are exploded from the uri like [item] => "phone" 3016 @discussion HTML select "combobox"s can only return 1 "value" per item, to break that limitation you 3017 can use that 1 item like a "fake URI", meaning you make a single string store structured data 3018 by using the standard syntax of a HTTP GET URI, see the example 3019 @example HTTP GET URI, example 3020 < select name="fake_uri_data" > < option value="&item=phone&action=dial&touchtone=1" > ( ... etc ... ) 3021 repeat with html entities for the doc parser 3022 < select name="fake_uri_data" > < option value="&item=phone&action=dial&touchtone=1" > ( ... etc ... ) 3023 In an HTTP POST event, this would appear as in the example 3024 $this->ref_POST["fake_uri_data"] => "&item=phone&action=dial&touchtone=1" 3025 Then you feed that string into this function and you get back an associave array like this 3026 return["item"] => "phone" 3027 return["action"] => "dial" 3028 return["touchtone"] => "1" 3029 NOTE: this differs from PHP's parse_str() because this function will NOT attempt to decode the urlencoded values. 3030 In this way you may store many data elements in a single HTML "option" value=" " tag. 3031 @author Angles 3032 @access Public 3033 */ 3034 function decode_fake_uri($uri_type_string='', $raise_up=False) 3035 { 3036 /* 3037 $fake_url_b = explode('&', $uri_type_string); 3038 if ($this->debug_args_input_flow > 2) { echo 'mail_msg: decode_fake_uri: $fake_url_b = explode("&", '.$uri_type_string.') dump:<pre>'; print_r($fake_url_b); echo '</pre>'; } 3039 3040 $fake_url_b_2 = array(); 3041 while(list($key,$value) = each($fake_url_b)) 3042 { 3043 $explode_me = trim($fake_url_b[$key]); 3044 if ((string)$explode_me != '') 3045 { 3046 $exploded_parts = explode('=', $explode_me); 3047 $fake_url_b_2[$exploded_parts[0]] = $exploded_parts[1]; 3048 } 3049 } 3050 if ($this->debug_args_input_flow > 2) { echo 'mail_msg: decode_fake_uri: $fake_url_b_2 (sub parts exploded and made into an associative array) dump:<pre>'; print_r($fake_url_b_2); echo '</pre>'; } 3051 return $fake_url_b_2; 3052 */ 3053 3054 $embeded_data = array(); 3055 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): ENTERED $uri_type_string ['.$uri_type_string.'] <br />'); } 3056 parse_str($uri_type_string, $embeded_data); 3057 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): parse_str('.$uri_type_string.', into $embeded_data DUMP:', $embeded_data); } 3058 3059 // NOTE PARSE_STR ***WILL ADD SLASHES*** TO ESCAPE QUOTES 3060 // NO MATTER WHAT YOUR MAGIC SLASHES SETTING IS 3061 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): NOTE PARSE_STR ***WILL ADD SLASHES*** TO ESCAPE QUOTES NO MATTER WHAT YOUR MAGIC SLASHES SETTING IS **stripping slashes NOW***'); } 3062 if (isset($embeded_data['folder'])) 3063 { 3064 $embeded_data['folder'] = stripslashes($embeded_data['folder']); 3065 } 3066 if (isset($embeded_data['msgball']['folder'])) 3067 { 3068 $embeded_data['msgball']['folder'] = stripslashes($embeded_data['msgball']['folder']); 3069 } 3070 3071 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): post "stripslashes" parse_str('.$uri_type_string.', into $embeded_data DUMP:', $embeded_data); } 3072 3073 // some embeded uri-faked data needs to be raised up one level from sub-elements to top level 3074 if ($raise_up) 3075 { 3076 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): attempt to raise up data one level in the array <br />'); } 3077 $count_embeded = count($embeded_data); 3078 if ($count_embeded == 1) 3079 { 3080 @reset($embeded_data); 3081 $new_top_level = array(); 3082 while(list($key,$value) = each($embeded_data)) 3083 { 3084 $new_top_level = $embeded_data[$key]; 3085 //break; 3086 } 3087 // re-urlencode folder names, and make acctnum 's integers 3088 /* 3089 // NOT NECESSARY HERE 3090 if ((is_array($new_top_level)) 3091 && (count($new_top_level) > 0)) 3092 { 3093 $loops = count($new_top_level); 3094 for($i=0;$i<$loops;$i++) 3095 { 3096 // re-urlencode folder names, because "prep_folder_in" is supposed to be where it gets urldecoded 3097 if ((isset($this_array_item[$i]['folder'])) 3098 && ((string)$this_array_item[$i]['folder'] != '')) 3099 { 3100 $re_urlencoded_folder = urlencode($this_array_item[$i]['folder']); 3101 if ($this->debug_args_input_flow > 1) { echo 'mail_msg: decode_fake_uri: re-urlencode (hopefully) folder element $this_array_item['.$i.'][folder] from ['.$this_array_item[$i]['folder'].'] into ['.$re_urlencoded_folder.'] <br />'; } 3102 $this_array_item[$i]['folder'] = $re_urlencoded_folder; 3103 } 3104 if ((isset($this_array_item[$i]['acctnum'])) 3105 && ((string)$this_array_item[$i]['acctnum'] != '')) 3106 { 3107 $make_int_acctnum = (int)$this_array_item[$i]['acctnum']; 3108 if ($this->debug_args_input_flow > 1) { echo 'mail_msg: decode_fake_uri: $make_int_acctnum (hopefully) acctnum element $this_array_item['.$i.'][acctnum] from ['.serialize($this_array_item[$i]['acctnum']).'] into ['.serialize($make_int_acctnum).'] <br />'; } 3109 $this_array_item[$i]['acctnum'] = $make_int_acctnum; 3110 } 3111 } 3112 } 3113 */ 3114 // replace result with $new_top_level 3115 $embeded_data = $new_top_level; 3116 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): raise embeded up to $new_top_level DUMP:', $new_top_level); } 3117 } 3118 else 3119 { 3120 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): original result had more than one element, can not raise <br />'); } 3121 } 3122 } 3123 // parse_str will "urldecode" the folder string, we need to re-urlencode it, 3124 // because "prep_folder_in" is supposed to be where it gets urldecoded 3125 while(list($key,$value) = each($embeded_data)) 3126 { 3127 if ((strstr($key, 'folder')) 3128 && ((string)$embeded_data[$key] != '')) 3129 { 3130 //$re_urlencoded_folder = urlencode($embeded_data[$key]); 3131 $re_urlencoded_folder = $this->prep_folder_out($embeded_data[$key]); 3132 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): re-urlencode (hopefully) folder element $embeded_data['.$key.'] from ['.$embeded_data[$key].'] into ['.$re_urlencoded_folder.'] <br />'); } 3133 $embeded_data[$key] = $re_urlencoded_folder; 3134 } 3135 elseif ((strstr($key, 'acctnum')) 3136 && ((string)$embeded_data[$key] != '')) 3137 { 3138 $make_int_acctnum = (int)$embeded_data[$key]; 3139 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): $make_int_acctnum (hopefully) acctnum element $embeded_data['.$key.'] from ['.serialize($embeded_data[$key]).'] into ['.serialize($make_int_acctnum).'] <br />'); } 3140 $embeded_data[$key] = $make_int_acctnum; 3141 } 3142 } 3143 3144 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): final $embeded_data (sub parts made into an associative array) DUMP:', $embeded_data); } 3145 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: decode_fake_uri('.__LINE__.'): LEAVING <br />'); } 3146 return $embeded_data; 3147 } 3148 3149 /*! 3150 @function grab_class_args_gpc 3151 @abstract grab data from $this->ref_POST and $this->ref_GET, looking for var names 3152 listed in the $this->known_external_args[] array, and fill various class arg variables with the available data. 3153 @result none, this is an object call 3154 @discussion to further seperate the mail functionality from php itself, this function will perform 3155 the variable handling of the traditional php page view Get Post Cookie (no cookie data used here though) 3156 The same data could be grabbed from any source, XML-RPC for example, insttead of the php GPC vars, 3157 so this function could (should) have an equivalent XML-RPC version to handle filling these class variables 3158 from an alternative source. This function looks for all the var names listed in the 3159 $this->known_external_args[] array. Therefor, by adding something to that array, it will be looked 3160 for here. This is similar to the new phpgwapi "get_var" function, but does less syntax checking (validation), and 3161 has code to handle URI type data that could be embedded in certain GPC vars that we look for. Some validation 3162 is done here, but certainly more could be added using the "get_var" in the future. 3163 UPDATE re RH8 php+apache2 bug. UPDATE this function 3164 now handles 2 bugs associated with RH8 php with apache2. The FIRST bug is with POST data designed 3165 to be a simple array when POSTed and read by php, this is the un-numbered array, not associative, the 3166 type of array you get with a succession of "some_array[] = X+1" calls in php code, and with form data 3167 where the key could be "some_array[]" and the value might be depenant on a check box, for example. This 3168 particular type of array can have the buggy behavior of having TWO of every element. Typically, the array 3169 when dumped will show the desired array, but then also have that same array again starting at the next 3170 element after the real array is done. So really you get an array that is really 2 sets of itself all in one array. 3171 The SECOND bug is where certain POSTed "key=value" string can get erronously added an element 3172 of an array from the same form, but that is supposed to be a seperate peice of data. That erronously 3173 added item will have its real "key=value" pair in the real place it should be AND also tacked on to 3174 one of the POSTed array items, where these items are strings. There were a few places in this function 3175 that required cleaning the POSTed data of these 2 types of bugs. 3176 @author Angles 3177 @access Public 3178 */ 3179 function grab_class_args_gpc() 3180 { 3181 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): ENTERING<br />'); } 3182 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): $this->ref_POST DUMP:', $this->ref_POST); } 3183 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): $this->ref_GET DUMP:', $this->ref_GET); } 3184 3185 // ---- extract any "fake_uri" embedded data from HTTP_POST_VARS ---- 3186 // note: this happens automatically for HTTP_GET_VARS 3187 // NOTE this WILL ALTER $_POST inserting processed values for later use (could this be avoided?) 3188 if (is_array($this->ref_POST)) 3189 { 3190 while(list($key,$value) = each($this->ref_POST)) 3191 { 3192 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): looking for "_fake_uri" token in HTTP_POST_VARS ['.$key.'] = '.$this->ref_POST[$key].'<br />'); } 3193 if ($key == 'delmov_list') 3194 { 3195 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): FOUND "delmov_list_fake_uri" needs decoding HTTP_POST_VARS['.$key.'] = ['.$this->ref_POST[$key].'] <br />'); } 3196 // apache2 on test RH8.0 box submits "delmov_list" array with duplicate items in it, track this 3197 $seen_delmov_list_items=array(); 3198 $sub_loops = count($this->ref_POST[$key]); 3199 for($i=0;$i<$sub_loops;$i++) 3200 { 3201 // bug2: apache2 on test RH8.0 box submits "delmov_list" array with "what=delall" tacked on to one of the array items 3202 if (strstr($this->ref_POST[$key][$i], 'what=delall')) 3203 { 3204 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): (apache2 bug2) **fixing** "delmov_list" array has string "what=delall" added to one item ['.$this->ref_POST[$key][$i].'] <br />'); } 3205 $this->ref_POST[$key][$i] = str_replace('what=delall', '', $this->ref_POST[$key][$i]); 3206 } 3207 3208 // bug1: apache2: do duplicate test on the "delmov_list" array items 3209 if (in_array($this->ref_POST[$key][$i], $seen_delmov_list_items) == True) 3210 { 3211 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): <u>unsetting</u> and *skipping* duplicate (buggy apache2) "delmov_list" array item ['.$this->ref_POST[$key][$i].'] <br />'); } 3212 $this->ref_POST[$key][$i] = ''; 3213 // can I UNSET this and have the next $i index item actually be the next one 3214 // YES, a) array count calculated before loop, and b) does not squash array to unset an item 3215 unset($this->ref_POST[$key][$i]); 3216 //array_splice($this->ref_POST[$key], $i, 1); 3217 // NOTE USE OF CONTINUE COMMAND HERE! 3218 // we do not increase $ii because the next array item just fell into the current slot 3219 continue; 3220 } 3221 else 3222 { 3223 // track seen items for duplicate test 3224 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): good (not duplicate, not buggy apache2) "delmov_list" array item ['.$this->ref_POST[$key][$i].'] <br />'); } 3225 $tmp_next_idx = count($seen_delmov_list_items); 3226 $seen_delmov_list_items[$tmp_next_idx] = $this->ref_POST[$key][$i]; 3227 } 3228 // if we get here, it is not duplicate, go ahead 3229 $sub_embedded_data = array(); 3230 // True = attempt to "raise up" embedded data to top level 3231 $sub_embedded_data = $this->decode_fake_uri($this->ref_POST[$key][$i], True); 3232 $this->ref_POST[$key][$i] = $sub_embedded_data; 3233 } 3234 // increment our shadow iteation count 3235 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): decoded ARRAY "_fake_uri" data: HTTP_POST_VARS['.$key.'] data DUMP:', $this->ref_POST[$key]); } 3236 } 3237 elseif (strstr($key, '_fake_uri')) 3238 { 3239 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): FOUND "_fake_uri" token in HTTP_POST_VARS['.$key.'] = ['.$this->ref_POST[$key].'] <br />'); } 3240 $embedded_data = array(); 3241 $embedded_data = $this->decode_fake_uri($this->ref_POST[$key]); 3242 // Strip "_fake_uri" from $key and insert the associative array into HTTP_POST_VARS 3243 $new_key = str_replace('_fake_uri', '', $key); 3244 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): embedded "_fake_uri" data will be inserted into POST VARS with key name: ['.$new_key.'] = ['.$this->ref_POST[$key].'] <br />'); } 3245 $this->ref_POST[$new_key] = array(); 3246 $this->ref_POST[$new_key] = $embedded_data; 3247 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): decoded "_fake_uri" data: HTTP_POST_VARS['.$new_key.'] data DUMP:', $this->ref_POST[$new_key]); } 3248 } 3249 /* 3250 elseif ($key == 'delmov_list') 3251 { 3252 if ($this->debug_args_input_flow > 1) { echo 'mail_msg: grab_class_args_gpc: FOUND "delmov_list" needs decoding HTTP_POST_VARS['.$key.'] = ['.$this->ref_POST[$key].'] <br />'; } 3253 $sub_loops = count($this->ref_POST[$key]); 3254 for($i=0;$i<$sub_loops;$i++) 3255 { 3256 $sub_embedded_data = array(); 3257 $sub_embedded_data = $this->decode_fake_uri($this->ref_POST[$key][$i]); 3258 $this->ref_POST[$key][$i] = $sub_embedded_data; 3259 } 3260 if ($this->debug_args_input_flow > 2) { echo 'mail_msg: grab_class_args_gpc: decoded ARRAY "_fake_uri" data: HTTP_POST_VARS['.$key.'] data dump: <pre>'; print_r($this->ref_POST[$key]); echo '</pre>'; } 3261 } 3262 */ 3263 } 3264 } 3265 3266 $got_args = array(); 3267 // insert *known* external args we find into $got_args[], then return that data 3268 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): about to loop thru $this->known_external_args<br />'); } 3269 $loops = count($this->known_external_args); 3270 for($i=0;$i<$loops;$i++) 3271 { 3272 $this_arg_name = $this->known_external_args[$i]; 3273 //if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * * (grab pref - external) $this_arg_name: ['.$this_arg_name.']<br />'); } 3274 if (isset($this->ref_POST[$this_arg_name])) 3275 { 3276 if ($this->debug_args_input_flow> 2) { $this->dbug->out(' * * (grab pref - external)('.__LINE__.') $this->ref_POST['.$this_arg_name.'] IS set to ['.$this->ref_POST[$this_arg_name].']<br />'); } 3277 $got_args[$this_arg_name] = $this->ref_POST[$this_arg_name]; 3278 } 3279 elseif (isset($this->ref_GET[$this_arg_name])) 3280 { 3281 if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * * (grab pref - external)('.__LINE__.') $this->ref_GET['.$this_arg_name.'] IS set to ['.serialize($this->ref_GET[$this_arg_name]).']<br />'); } 3282 $got_args[$this_arg_name] = $this->ref_GET[$this_arg_name]; 3283 3284 // STRIPSLASHES IF NEEDED 3285 if (($this_arg_name == 'msgball') 3286 || ($this_arg_name == 'fldball')) 3287 { 3288 // php will automayically urldecode the folder, we don't like this 3289 // AND PHP MIGHT ADD GPC SLASHES WE DO NOT WANT!!!!! depending on your ini settings 3290 // use custom "stripslashes_gpc" function here because the slashes at this point would have been added ONLY by php itself 3291 // i.e. we have not yet used "parse_str" yet, that always addes slashes, but not using it yet means any slashes are GPC slashes 3292 $not_urlencoded_but_stripslashed_folder = $this->stripslashes_gpc($got_args[$this_arg_name]['folder']); 3293 // now we have no unwanted slashes, so put this back in the input args 3294 if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * * (grab pref - external)('.__LINE__.'): msgball[folder] STRIPSLASH watch: $got_args[$this_arg_name]["folder"]: ['.htmlspecialchars($got_args[$this_arg_name]['folder']).']; $not_urlencoded_but_stripslashed_folder: ['.htmlspecialchars($not_urlencoded_but_stripslashed_folder).']<br />'); } 3295 $got_args[$this_arg_name]['folder'] = $not_urlencoded_but_stripslashed_folder; 3296 $not_urlencoded_but_stripslashed_folder = ''; 3297 unset($not_urlencoded_but_stripslashed_folder); 3298 } 3299 // ADD "uri" element to incoming "msgball" arg 3300 // so forms may pass this "msgball" on to the next page view 3301 if ($this_arg_name == 'msgball') 3302 { 3303 // php will automayically urldecode the folder, we don't like this 3304 // we want the folder value to be URLENCODED, so we need to re-urlencode it 3305 $re_urlencoded_folder = $this->prep_folder_out($got_args[$this_arg_name]['folder']); 3306 $got_args[$this_arg_name]['folder'] = $re_urlencoded_folder; 3307 $got_args[$this_arg_name]['uri'] = 3308 'msgball[msgnum]='.$got_args[$this_arg_name]['msgnum'] 3309 .'&msgball[folder]='.$got_args[$this_arg_name]['folder'] 3310 .'&msgball[acctnum]='.$got_args[$this_arg_name]['acctnum']; 3311 if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * * (grab pref - external)('.__LINE__.') made msgball URI, added it to msgball[]: DUMP:', $got_args[$this_arg_name]); } 3312 } 3313 } 3314 else 3315 { 3316 if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * (grab pref - external)('.__LINE__.') neither POST nor GET vars have this item set ['.$this_arg_name.'] <br />'); } 3317 } 3318 } 3319 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): post-loop (external args) $got_args[] DUMP:', $got_args); } 3320 3321 // in order to know wgat account's arg array to insert $got_args[] into, we need to determine what account 3322 // we are dealing with before we can call $this->set_arg_array or "->get_isset_arg" or "->get_arg_value", etc... 3323 // so whoever called this function should obtain that before calling $this->set_arg_array() with the data we return here 3324 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: grab_class_args_gpc('.__LINE__.'): LEAVING, returning $got_args<br />'); } 3325 return $got_args; 3326 } 3327 3328 /*! 3329 @function grab_class_args_xmlrpc 3330 @abstract grab data an XML-RPC call and fill various class arg variables with the available data 3331 @result none, this is an object call 3332 @discussion functional relative to function "grab_class_args_gpc()", except this function grabs the 3333 data from an alternative, non-php-GPC, source 3334 NOT YET IMPLEMENTED 3335 @author Angles 3336 @access Public 3337 */ 3338 function grab_class_args_xmlrpc() 3339 { 3340 // STUB, for future use 3341 echo 'call to un-implemented function grab_class_args_xmlrpc'; 3342 } 3343 3344 3345 /*! 3346 @function get_best_acctnum 3347 @abstract search a variety of vars to find a legitimate account number, fallsback to $this->get_acctnum 3348 @param $args_array ARRAY that was passed to ->begin_request, pass that into here if possible, it is a primary source 3349 @param $got_args ARRAY of the *External* params (args) fed to this script via GPC or other methods. 3350 Note: these are NOT the "internal args". 3351 @param $force_feed_acctnum .DEPRECIATED. INTEGER if for some reason you want to force an account number. DEPRECIATED. 3352 @result integer, most legitimate account number that was obtained 3353 @discussion Run early in the script run to establish the most likely account that the rest 3354 of the script run will be concerned with. See this function itself, or turn on debugging output, 3355 to see what places this function looks to for the "best acctnum". 3356 It looks in a series of places, in order of importance to this function, each step of the way if no 3357 acctnum is found there, the function looks in the next place, and so on, until an acctnum is 3358 found or a fallback, usually "0" for the default email account, is used. See the function 3359 $this->get_acctnum for more info. If this function has not already found and stored a good 3360 acctnum value, it is most likely that $this->get_acctnum will return the "fallback_default_acctnum" usually "0". 3361 This "best acctnum" applies to the typical situations where you are viewing a list of 3362 messages in a particular account's folder. HOWEVER, if the list of 3363 messages is composed of messages from different accounts, such as is possible with testing filter rules, 3364 then there would be no "best acctnum" because no single account is being looked at. In any case 3365 each message item should be in the form of a "msgball" which carries with it the acctnum the 3366 message is associated with (amoung other things). Even so, the far more typical scenario is 3367 viewing a list of messages from the same account and folder. Also, when viewing any one messages 3368 contents, the "best acctnum" is obviously the account that message came from. When viewing 3369 folder contents, the folder we want to look at is passed in the form of a "fldball" which is an associative 3370 array containing "folder" and "acctnum", so this function would use that acctnum as the "best acctnum". 3371 Typically we are dealing with either "fldball" or "msgball" data which carry with them the 3372 acctnum they are associated with. Being able to determine the "best acctnum" that 3373 applies to a particular page view is helpful since this value will be stored and available 3374 using function $this->get_acctnum() which is easy to call from anyewhere. 3375 Before it became possible to operate on mesages from seperate folders and accounts in the same page, 3376 this "best acctnum" has more importance, but still it is most common not to have a list of messages 3377 from different sources, so this function is useful in a majority of the usages we will handle. Since 3378 this is true, many functions in this class, like "get_arg_value", take a param for "acctnum" that is 3379 OPTIONAL because if not provided any function can obtain an acctnum value by calling 3380 $this->get_acctnum() which returns the value which was found here. 3381 @author Angles 3382 @access Private 3383 */ 3384 function get_best_acctnum($args_array='', $got_args='', $force_feed_acctnum='') 3385 { 3386 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): ENTERING, param $force_feed_acctnum ['.$force_feed_acctnum.']<br />'); } 3387 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): parm $args_array[] DUMP:', $args_array); } 3388 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): parm $got_args[] DUMP:', $got_args); } 3389 3390 // --- which email account do are these args intended to apply to ---- 3391 // ORDER OF PREFERENCE for determining account num: just look at the code, it has comments 3392 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": searching...: <br />'); } 3393 // initialize 3394 $acctnum = ''; 3395 3396 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): get acctnum from feed args if possible<br />'); } 3397 $found_acctnum = False; 3398 while(list($key,$value) = each($args_array)) 3399 { 3400 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (acctnum search) this loop feed arg : ['.$key.'] => ['.serialize($args_array[$key]).'] <br />'); } 3401 // try to find feed acctnum value 3402 if ($key == 'fldball') 3403 { 3404 $fldball = $args_array[$key]; 3405 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (acctnum search) $args_array passed in $fldball[] : '.serialize($fldball).'<br />'); } 3406 $acctnum = (int)$fldball['acctnum']; 3407 3408 // SET OUR ACCTNUM ACCORDING TO FEED ARGS 3409 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (acctnum search) ACCTNUM from $args_array fldball : ['.$acctnum.']<br />'); } 3410 $found_acctnum = True; 3411 break; 3412 } 3413 elseif ($key == 'msgball') 3414 { 3415 $msgball = $args_array[$key]; 3416 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (acctnum search) $args_array passed in $msgball[] : '.serialize($msgball).'<br />'); } 3417 $acctnum = (int)$msgball['acctnum']; 3418 // SET OUR ACCTNUM ACCORDING TO FEED ARGS 3419 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (acctnum search) ACCTNUM from $args_array msgball : ['.$acctnum.']<br />'); } 3420 $found_acctnum = True; 3421 break; 3422 } 3423 elseif ($key == 'acctnum') 3424 { 3425 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (acctnum search) $args_array passed in "acctnum" : '.serialize($args_array[$key]).'<br />'); } 3426 $acctnum = (int)$args_array[$key]; 3427 // SET OUR ACCTNUM ACCORDING TO FEED ARGS 3428 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (acctnum search) ACCTNUM from $args_array "acctnum" feed args : ['.$acctnum.']<br />'); } 3429 $found_acctnum = True; 3430 break; 3431 } 3432 } 3433 // did the above work? 3434 if ($found_acctnum == True) 3435 { 3436 // SET THE ACCTNUM AND RETURN IT 3437 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): (from $args_array) * * * *SETTING CLASS ACCTNUM* * * * by calling $this->set_acctnum('.serialize($acctnum).')<br />'); } 3438 $this->set_acctnum($acctnum); 3439 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): LEAVING early, $args_array had the data, returning $acctnum ['.serialize($acctnum).']<br />'); } 3440 return $acctnum; 3441 } 3442 3443 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": continue searching...: <br />'); } 3444 3445 // ok, now we need to broaden the search for a legit account number 3446 if ((isset($force_feed_acctnum)) 3447 && ((string)$force_feed_acctnum != '')) 3448 { 3449 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": will use function param $force_feed_acctnum=['.serialize($force_feed_acctnum).']<br />'); } 3450 $acctnum = (int)$force_feed_acctnum; 3451 } 3452 elseif ((isset($got_args['msgball']['acctnum'])) 3453 && ((string)$got_args['msgball']['acctnum'] != '')) 3454 { 3455 // we are requested to handle (display, move, forward, etc...) this msgball, use it's properties 3456 $acctnum = (int)$got_args['msgball']['acctnum']; 3457 // make sure this is an integer 3458 $got_args['msgball']['acctnum'] = $acctnum; 3459 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": will use GPC aquired $got_args[msgball][acctnum] : ['.serialize($got_args['msgball']['acctnum']).']<br />'); } 3460 } 3461 elseif ((isset($got_args['fldball']['acctnum'])) 3462 && ((string)$got_args['fldball']['acctnum'] != '')) 3463 { 3464 // we are requested to handle (display, .... ) data concerning this fldball, use it's properties 3465 $acctnum = (int)$got_args['fldball']['acctnum']; 3466 // make sure this is an integer 3467 $got_args['fldball']['acctnum'] = $acctnum; 3468 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": will use GPC aquired $got_args[fldball][acctnum] : ['.serialize($got_args['fldball']['acctnum']).']<br />'); } 3469 } 3470 elseif ((isset($got_args['source_fldball']['acctnum'])) 3471 && ((string)$got_args['source_fldball']['acctnum'] != '')) 3472 { 3473 // we are *probably* requested to delete or rename this fldball, use it's properties 3474 $acctnum = (int)$got_args['source_fldball']['acctnum']; 3475 // make sure this is an integer 3476 $got_args['source_fldball']['acctnum'] = $acctnum; 3477 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": will use GPC aquired $got_args[source_fldball][acctnum] : ['.serialize($got_args['source_fldball']['acctnum']).']<br />'); } 3478 } 3479 elseif ((isset($got_args['delmov_list'][0]['acctnum'])) 3480 && ((string)$got_args['delmov_list'][0]['acctnum'] != '')) 3481 { 3482 // at the very least we know that we'll need to login to this account to delete or move this particular msgball 3483 // also, we will need to open the particular folder where the msg is localted 3484 $acctnum = (int)$got_args['delmov_list'][0]['acctnum']; 3485 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": will use GPC aquired $got_args[delmov_list][0][acctnum] : ['.serialize($got_args['delmov_list'][0]['acctnum']).']<br />'); } 3486 } 3487 elseif ((isset($got_args['target_fldball']['acctnum'])) 3488 && ((string)$got_args['target_fldball']['acctnum'] != '')) 3489 { 3490 // at the very least we know we need to login to this account to append a message to a folder there 3491 // NOTE: we need not open the particular folder we are going to append to, 3492 // all we need is a stream to that particular account, "opened" folder is not important 3493 // therefor we can just use INBOX as the folder to log into in this case 3494 $acctnum = (int)$got_args['target_fldball']['acctnum']; 3495 // make sure this is an integer 3496 $got_args['target_fldball']['acctnum'] = $acctnum; 3497 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": will use GPC aquired $got_args[target_fldball][acctnum] : ['.serialize($got_args['target_fldball']['acctnum']).']<br />'); } 3498 } 3499 else 3500 { 3501 // FALLBACK 3502 // ok, we have NO acctnum in $args_array, did NOT get it from GPC got_args, nor the force fed $force_feed_acctnum 3503 // so, we grab the class's current value for $this->acctnum 3504 // $this->get_acctnum() will return a default value for us to use if $this->acctnum is not set 3505 // note, this is identical to $this->get_acctnum(True) because True is the default arg there if one is not passed 3506 // True means "return a default value, NOT boolean false, if $this->acctnum is not set 3507 $acctnum = $this->get_acctnum(True); 3508 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): "what acctnum to use": NO *incoming* acctnum specified, called $this->get_acctnum(True), got: ['.serialize($acctnum).']<br />'); } 3509 } 3510 3511 // SET THE ACCTNUM WITH THE "BEST VALUE" WE COULD FIND 3512 // DEPRECIATED - we no longer set it here 3513 //if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: get_best_acctnum: * * * *SETTING CLASS ACCTNUM* * * * by calling $this->set_acctnum('.serialize($acctnum).')<br />'); } 3514 //$this->set_acctnum($acctnum); 3515 3516 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: get_best_acctnum('.__LINE__.'): LEAVING, returning $acctnum ['.serialize($acctnum).']<br />'); } 3517 return $acctnum; 3518 } 3519 3520 /*! 3521 @function init_internal_args_and_set_them 3522 @abstract initialize Internally controlled params (args). MUST already have an acctnum 3523 @param $acctnum integer the current account number whose array we will fill with these initialized args 3524 @result none, this is an object call 3525 @discussion ALMOST DEPRECIATED. 3526 NOTE that the most IMPORTANT thing this does now is set interal arg 3527 "already_grab_class_args_gpc" to True, which serves as an ad-hoc flag indicating this class 3528 has already been through its typical initialization procedures. But that was not the 3529 intended purpose here, it just happened that way, partly for the simple reason that this 3530 function is called after the "grab_external_args" function. This function had more meaning 3531 once, back when a now depreciated and gone function used it. Now this is mostly an 3532 outdated, not needed, not really used function. Even so, it turns out that keeping an 3533 array called $this->known_internal_args[] is helpful from a development standpoint, just 3534 to help the coder remember what args this class is passing around to itself. These internal args are 3535 different from the "external" args because these internal args are NEVER filled from external sources, 3536 such as GET and POST or possible XML-RPC sources, which are considered external sources of data. 3537 A side effect is that this function will actually set all the args listed in that "known_internal_args" 3538 array, which is bad because you can not use the set vs. not set comparison if they are set always. 3539 For that reason there are currently some internal args not listed in the "known_internal_args" 3540 array. This probably will be cleaned up in the future. 3541 @author Angles 3542 @access Public 3543 */ 3544 function init_internal_args_and_set_them($acctnum='') 3545 { 3546 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: init_internal_args: ENTERING, (parm $acctnum=['.serialize($acctnum).'])<br />'); } 3547 // we SHOULD have already obtained a valid acctnum before calling this function 3548 if (!(isset($acctnum)) 3549 || ((string)$acctnum == '')) 3550 { 3551 $acctnum = $this->get_acctnum(); 3552 } 3553 3554 // INTERNALLY CONTROLLED ARGS 3555 // preserve pre-existing value, for which "acctnum" must be already obtained, so we 3556 // know what account to check for existing arg values when we use "get_isset_arg" or "get_arg_value" 3557 $internal_args = Array(); 3558 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: init_internal_args: about to loop thru $this->known_internal_args<br />'); } 3559 $loops = count($this->known_internal_args); 3560 for($i=0;$i<$loops;$i++) 3561 { 3562 $this_arg_name = $this->known_internal_args[$i]; 3563 //if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * * (grab pref - internal) $this_arg_name: '.$this_arg_name.'<br />'); } 3564 // see if there is a value we can preserve for this arg 3565 if ($this->get_isset_arg($this_arg_name)) 3566 { 3567 $preserve_this = $this->get_arg_value($this_arg_name); 3568 if ($this->debug_args_input_flow> 2) { $this->dbug->out(' * * (grab pref - internal) preserving internal pre-existing arg: ['.$this_arg_name.'] = ['.$preserve_this.']<br />'); } 3569 $internal_args[$this_arg_name] = $preserve_this; 3570 } 3571 else 3572 { 3573 if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * (grab pref - internal) no pre-existing value for ['.$this_arg_name.'], using initialization default: <br />'); } 3574 if ($this_arg_name == 'folder_status_info') 3575 { 3576 $internal_args['folder_status_info'] = array(); 3577 } 3578 elseif ($this_arg_name == 'folder_list') 3579 { 3580 $internal_args['folder_list'] = array(); 3581 } 3582 elseif ($this_arg_name == 'mailsvr_callstr') 3583 { 3584 $internal_args['mailsvr_callstr'] = ''; 3585 } 3586 elseif ($this_arg_name == 'mailsvr_namespace') 3587 { 3588 $internal_args['mailsvr_namespace'] = ''; 3589 } 3590 elseif ($this_arg_name == 'mailsvr_delimiter') 3591 { 3592 $internal_args['mailsvr_delimiter'] = ''; 3593 } 3594 elseif ($this_arg_name == 'mailsvr_stream') 3595 { 3596 $internal_args['mailsvr_stream'] = ''; 3597 } 3598 elseif ($this_arg_name == 'mailsvr_account_username') 3599 { 3600 $internal_args['mailsvr_account_username'] = ''; 3601 } 3602 // experimental (by it being *here*): this arg is handles elsewhere, but Iput it here 3603 // to help remember and be consistant about accounting for all args we may use 3604 // UPDATE: "expunge_folders" can NOT BE HERE because it should NOT EXIST unless set during a move or delete 3605 // putting it here will initialize it to a value of "" (empty string) which is different than unset. 3606 //elseif ($this_arg_name == 'expunge_folders') 3607 //{ 3608 // $internal_args['expunge_folders'] = ''; 3609 //} 3610 // experimental: Set Flag indicative we've run thru this function 3611 elseif ($this_arg_name == 'already_grab_class_args_gpc') 3612 { 3613 $internal_args['already_grab_class_args_gpc'] = True; 3614 } 3615 } 3616 } 3617 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: init_internal_args: post-loop (internal args) $internal_args[] DUMP:', $internal_args); } 3618 3619 3620 // clear old args (if any) and set the args we just obtained (or preserved) 3621 //$this->unset_all_args(); 3622 // set new args, some may require processing (like folder will go thru prep_folder_in() automatically 3623 //while(list($key,$value) = each($internal_args)) 3624 //{ 3625 // $this->set_arg_value($key, $internal_args[$key]); 3626 //} 3627 3628 // use this one call to do it all 3629 //$this->set_arg_array($internal_args); 3630 3631 // add these items to the args array for the appropriate account 3632 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: init_internal_args: about to add $internal_args to acounts class args array<br />'); } 3633 while(list($key,$value) = each($internal_args)) 3634 { 3635 if ($this->debug_args_input_flow > 2) { $this->dbug->out(' * mail_msg: init_internal_args: (looping) setting internal arg: $this->set_arg_value('.$key.', '.$internal_args[$key].', '.$acctnum.'); <br />'); } 3636 $this->set_arg_value($key, $internal_args[$key], $acctnum); 3637 //$this->set_arg_value($key, $internal_args[$key]); 3638 } 3639 3640 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: grab_class_args_gpc: LEAVING, returning $internal_args<br />'); } 3641 return $internal_args; 3642 } 3643 3644 /*! 3645 @function get_best_folder_arg 3646 @abstract search a variety of vars to find a legitimate folder value to open on the mail server number, 3647 @param $args_array ARRAY that was passed to ->begin_request, pass that into here if possible, it is a primary source 3648 @param $got_args ARRAY of the *External* params (args) fed to this script via GPC or other methods 3649 Note these are NOT the "internal args". 3650 @param $acctnum INTEGER used to querey various already-set args 3651 @result string, most legitimate folder value that was obtained 3652 @discussion The return folder string MUST *NOT* BE URLENCODED. 3653 It is an artifact of this apps development that this arg exists and is not urlencoded. 3654 Once upon a time, any one page view could be associated with ONLY one folder at a time. 3655 This is no longer a limitation, but a VAST majority of the time it is true that 3656 we are only concerned with one particular folder for a page view. A similar discussion is in the 3657 comments for function "get_best_acctnum". As it happens, now this app uses things called 3658 "fldball" and "msgball" because the advent of multiple accounts, and the ability to handle 3659 messages from any folder from any account at any time, required that a description of a 3660 folder or message carry with it enough info to bunch all those possibilities into one structure. 3661 We call these "fldball" and "msgball", at the least they contain elements "folder" and "acctnum", 3662 and "msgball" will additionally contain more data such as "msgnum". But I digress. In the past 3663 it was only necessary to know the one folder we cared about for the script run, and mostly 3664 this is still applicable. This function looks in a variety of places for that, see the function itself for 3665 details, including looking for certain fldball or msgball args. SECONDLY it is an artifact 3666 of this apps development that this arg value is NOT urlencoded. This is now unusual because 3667 the fldball and msgball data ALWAYS keep their "folder" data URLENCODED. This STAYS 3668 urlencoded up until it absolutely needs to be decoded, such as when sending a command to the 3669 IMAP server. So it is a notable exception that this arg is not urlencoded. But that is because it 3670 never was ever urlencoded "in the old days" so functions that look for the simple arg "folder" 3671 expected a non-urlencoded value. DIGRESSION - the urlencoding of the folder names makes it 3672 easier to cache the names in a database, which can be sensitive to some chars if not encoded. 3673 And if you know a fldball always has urlencoded folder value then you can more 3674 accurately compare two different fldballs more quickly. If one were urlencoded and the other 3675 not, then identical folder names would not match in a string comparison. So SQL calls 3676 expected a urlencoded folder name. If not for this expectation, we may not pull the 3677 desired data from the database, and perhaps leave unneeded data there because of this. 3678 MORE DIGRESSION - fldball and msgball data is in URI syntax when in string form, 3679 and by using function "ball_data_parse_str" that string can be turned into an associative 3680 array. Note that php function parse_str is used for this BUT see that function for more 3681 discussion on that topic, the result is that we keep the folder name urlencoded in that array. 3682 Usually we make the transformation into an array for ease of use inside a function, 3683 but the string URI syntax takes up less memory when dealing with huge message lists, and 3684 takes up less space cached in a database as compared to a serialized array with the same data. 3685 @author Angles 3686 @access Private 3687 */ 3688 function get_best_folder_arg($args_array='', $got_args='', $acctnum='') 3689 { 3690 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: get_best_folder_arg: ENTERING <br />'); } 3691 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: get_best_folder_arg: param $acctnum ['.$acctnum.'] ; parm $args_array[] DUMP:', $args_array); } 3692 if ($this->debug_args_input_flow > 2) { $this->dbug->out('mail_msg: get_best_folder_arg: param $acctnum ['.$acctnum.'] ; parm $got_args[] DUMP:', $got_args); } 3693 // initialize 3694 $processed_folder_arg = ''; 3695 // we SHOULD have already obtained a valid acctnum before calling this function 3696 if (!(isset($acctnum)) 3697 || ((string)$acctnum == '')) 3698 { 3699 $acctnum = $this->get_acctnum(); 3700 } 3701 // ---- Get Folder Value ---- 3702 // ORDER OF PREFERENCE for pre-processed "folder" input arg 3703 // (1) $args_array, IF FILLED, overrides any previous data or any other data source, look for these: 3704 // $args_array['folder'] 3705 // (2) GPC ['msgball']['folder'] 3706 // (3) GPC ['fldball']['folder'] 3707 // (4) GPC ['delmov_list'][0]['folder'] 3708 // (5) if "folder" arg it is already set, (probably during the reuse attempt, probably obtained from $args_array alreadt) then use that 3709 // (6) default to blank string, which "prep_folder_in()" changes to defaultg value INBOX 3710 3711 // note: it's OK to send blank string to "prep_folder_in", because it will return a default value of "INBOX" 3712 if ((isset($args_array['folder'])) 3713 && ($args_array['folder'] != '')) 3714 { 3715 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: $input_folder_arg chooses $args_array[folder] ('.$args_array['folder'].') over any existing "folder" arg<br />'); } 3716 $input_folder_arg = $args_array['folder']; 3717 } 3718 elseif ($this->get_isset_arg('["msgball"]["folder"]')) 3719 { 3720 $input_folder_arg = $this->get_arg_value('["msgball"]["folder"]'); 3721 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: $input_folder_arg chooses $this->get_arg_value(["msgball"]["folder"]): ['.$input_folder_arg.']<br />'); } 3722 //VERIFY 3723 $processed_folder_arg = $this->prep_folder_in($input_folder_arg, $this->get_arg_value('["msgball"]["acctnum"]')); 3724 // when putting back into the ball data we need to urlencode it because folder element in ball data stays urlencoded until the last monent 3725 $processed_folder_arg = urlencode($processed_folder_arg); 3726 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg('.__LINE__.'): after "prep_folder_in", $processed_folder_arg : ['.$processed_folder_arg.']<br />'); } 3727 // both these should be urlencoded so this is apples to apples comparison 3728 if ($processed_folder_arg != $input_folder_arg) 3729 { 3730 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg('.__LINE__.'): $processed_folder_arg != $input_folder_arg so about to call $this->set_arg_value(["msgball"]["folder"], $processed_folder_arg) <br />'); } 3731 $this->set_arg_value('["msgball"]["folder"]', $processed_folder_arg); 3732 } 3733 // now that is done, urldecode because a legacy quirk requires a urldecded return from this function 3734 $processed_folder_arg = urldecode($processed_folder_arg); 3735 } 3736 elseif ($this->get_isset_arg('["fldball"]["folder"]')) 3737 { 3738 $input_folder_arg = $this->get_arg_value('["fldball"]["folder"]'); 3739 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: $input_folder_arg chooses $this->get_arg_value(["fldball"]["folder"]): ['.$input_folder_arg.']<br />'); } 3740 //VERIFY 3741 $processed_folder_arg = $this->prep_folder_in($input_folder_arg, $this->get_arg_value('["fldball"]["acctnum"]')); 3742 // when putting back into the ball data we need to urlencode it because folder element in ball data stays urlencoded until the last monent 3743 $processed_folder_arg = urlencode($processed_folder_arg); 3744 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg('.__LINE__.'): after "prep_folder_in", $processed_folder_arg : ['.$processed_folder_arg.']<br />'); } 3745 // both these should be urlencoded so this is apples to apples comparison 3746 if ($processed_folder_arg != $input_folder_arg) 3747 { 3748 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg('.__LINE__.'): $processed_folder_arg != $input_folder_arg so about to call $this->set_arg_value(["fldball"]["folder"], $processed_folder_arg) <br />'); } 3749 $this->set_arg_value('["fldball"]["folder"]', $processed_folder_arg); 3750 } 3751 // now that is done, urldecode because a legacy quirk requires a urldecded return from this function 3752 $processed_folder_arg = urldecode($processed_folder_arg); 3753 } 3754 elseif ($this->get_isset_arg('delmov_list')) 3755 { 3756 // we know we'll need to loginto this folder to get this message and move/delete it 3757 // there may be other msgballs in the delmov_list array, but we know at the very list we'll need to open this folder anyway 3758 $this_delmov_list = $this->get_arg_value('delmov_list'); 3759 $input_folder_arg = $this_delmov_list[0]['folder']; 3760 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: $input_folder_arg chooses $this_delmov_list[0][folder]: ['.$input_folder_arg.']<br />'); } 3761 } 3762 else 3763 { 3764 if (($this->get_isset_arg('folder')) 3765 && ((string)trim($this->get_arg_value('folder')) != '')) 3766 { 3767 $input_folder_arg = $this->get_arg_value('folder'); 3768 } 3769 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: $input_folder_arg *might* chooses $this->get_arg_value(folder): ['.serialize($input_folder_arg).']<br />'); } 3770 3771 $input_folder_arg = (string)$input_folder_arg; 3772 $input_folder_arg = trim($input_folder_arg); 3773 if ($input_folder_arg != '') 3774 { 3775 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: $this->get_arg_value(folder) passes test, so $input_folder_arg chooses $this->get_arg_value(folder): ['.serialize($input_folder_arg).']<br />'); } 3776 } 3777 else 3778 { 3779 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: no folder value found, so $input_folder_arg takes an empty string<br />'); } 3780 $input_folder_arg = ''; 3781 } 3782 } 3783 // ---- Prep the Folder Name (remove encodings, verify it's long name (with namespace) 3784 // folder prepping does a lookup which requires a folder list which *usually* (unless caching) requires a login 3785 if ($processed_folder_arg != '') 3786 { 3787 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: we already obtained above a $processed_folder_arg ['.$processed_folder_arg.']<br />'); } 3788 } 3789 else 3790 { 3791 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: about to issue $processed_folder_arg = $this->prep_folder_in('.$input_folder_arg.')<br />'); } 3792 $processed_folder_arg = $this->prep_folder_in($input_folder_arg); 3793 } 3794 if ($this->debug_args_input_flow > 1) { $this->dbug->out('mail_msg: get_best_folder_arg: remember legacy quirk says return value from here should be urdecoded, eventhough msgball and fldball keep folder element urlencoded usually<br />'); } 3795 if ($this->debug_args_input_flow > 0) { $this->dbug->out('mail_msg: get_best_folder_arg: LEAVING, returning $processed_folder_arg value: ['.$processed_folder_arg.'] remember legacy quirk says return value from here should be urdecoded, eventhough msgball and fldball keep folder element urlencoded usually<br />'); } 3796 return $processed_folder_arg; 3797 } 3798 3799 3800 /**************************************************************************\ 3801 * END INPUT ARG/PARAM HANDLERS * 3802 * - - - - - - - - - - - - - - - - - - - - - - - - - * 3803 * BEGIN APPSESSION TEMPORARY CACHING HANDLERS * 3804 \**************************************************************************/ 3805 3806 // ACTUAL DATA ACCESS FUNCTIONS MOVED TO SO CLASS 3807 // HIGH LEVEL CACHING STUFF KEPT HERE 3808 /*! 3809 @function save_session_cache_item BEING OVERHAULED preliminary complete. 3810 @abstract TEMPORARY DATA CACHING server-side in the phpgw appsession cache. 3811 @param $data_name (string) 3812 @param $data (mixed) usually an array 3813 @param $acctnum (int) 3814 @param $extra_keys (string) optional info used to make the appsession "location" string for data that is 3815 part of a larger group of elements, this param will let us refer to this single element without using sub arrays 3816 @author Angles 3817 @discussion Server-side caching of limited, ephermal data, such as a list of messages from 3818 an imap search, saved to phpgw appsession. All appsession data gets deleted when the user logs out, which is 3819 why this is a temporary cache. NOTE: to cache an item you must add it to list of data items that 3820 has a handler here, otherwise we skip it. Handler need may be lifted in the future, but for now anything 3821 stored in the appsession cache requires a handler here because different types of data arrive here in different 3822 forms, and must be stored using that extra information to know where to put the data in the appsession 3823 cache array of data. For example, *some* cached items get meta_data saved with it, right now only the 3824 "msgball_list" is saved with other, related data. In the case of the "msgball_list", $meta_data["msgball_list"] 3825 and $meta_data["validity"] is what we should get fed into this function, where that meta_data "validity" data 3826 is used to verify if the cached "msgball_list" is valid, not-stale data, when restoring a "msgball_list" from the 3827 cache. Also. data is saved in the appsession data array starting at element 3828 "[_SESSION][phpgw_session][phpgw_app_sessions][email]" and from that we add the single element 3829 "dat" and from that all the information we cache is attached to that element of the array. All data REQUIRES 3830 an acctnum, as an integer, because that is the first thing we use to determine a location in the appsession 3831 array for the data. Then we use the data_name, the combination of [acctnum][data_name] is the least 3832 amount of info we need to put the more simple data in the appsession array, such as the cached "mailsvr_callstr". 3833 It would be saved here "[_SESSION][phpgw_session][phpgw_app_sessions][email][dat][$acctnum][mailsvr_callstr]" 3834 as the key and the actual mailsvr_callstr data is the value. The next step up in data requirement is the addition 3835 of the folder name to the array, such as for "folder_status_info" data, is gets saved at this key 3836 "[_SESSION][phpgw_session][phpgw_app_sessions][email][dat][$acctnum][folder_status_info][folder]" as its key. 3837 Them the most info we need to store cached data is for, currently, the "msg_structure" and "phpgw_header" 3838 which reauire the additional information that is the msgnum they apply to, so they are saved with this 3839 as their key, as in the case of "msg_structure", 3840 "[_SESSION][phpgw_session][phpgw_app_sessions][email][dat][$acctnum][msg_structure][folder][msgnum]". 3841 This allows us to directly access this appsession array if we want, and to quickly access or expire individual 3842 parts of the data without having to loop through a lot of array to find what we want. SUBJECT TO CHANGE. 3843 @example This is not really an example but it does explain where this data is kept in memory. 3844 [HTTP_SESSION_VARS][phpgw_session][phpgw_app_sessions][email] 3845 [_SESSION][phpgw_session][phpgw_app_sessions][email] 3846 This is also accessable thru this 3847 GLOBALS[phpgw_session][phpgw_app_sessions][email] 3848 @access private 3849 */ 3850 function save_session_cache_item($data_name='misc',$data,$acctnum='',$extra_keys='') 3851 { 3852 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): ENTERED, $this->session_cache_enabled='.serialize($this->session_cache_enabled).', $data_name: ['.$data_name.'], $acctnum (optional): ['.$acctnum.'], $extra_keys: ['.$extra_keys.']<br />'); } 3853 $has_handler = False; 3854 3855 if ((!isset($acctnum)) 3856 || ((string)$acctnum == '')) 3857 { 3858 $acctnum = $this->get_acctnum(); 3859 } 3860 3861 if ($this->session_cache_enabled == False) 3862 { 3863 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, because $this->session_cache_enabled='.serialize($this->session_cache_enabled).', so not this basic stuff, and not the extra "extreme cache" stuff, nothing can use the appsession cache.<br />'); } 3864 // LEAVING 3865 return False; 3866 } 3867 // IF EMPTY DATA - LEAVE 3868 if (!$data) 3869 { 3870 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING with ERROR, no $data param was provided for $data_name ['.$data_name.'] $acctnum ['.$acctnum.'], we gotta return false because no data was saved<br />'); } 3871 // LEAVING 3872 return False; 3873 } 3874 3875 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): extra param (if provided) $extra_keys: ['.serialize($extra_keys).'] <br />'); } 3876 3877 // 1st -- session_cache_enabled stuff 3878 // this stuff is cached REGARDLESS of extreme mode, extreme mode is *extra* caching in addition to the "session_cache_enabled" stuff 3879 // process the data according to what it is 3880 if ($data_name == 'msgball_list') 3881 { 3882 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): session_cache_enabled and data exists AND $data_name ['.$data_name.'] has a handler<br />'); } 3883 3884 // we damn well better have a msgball_list or else we have nothing to save 3885 if ((isset($data['msgball_list']) == False) 3886 || (!$data['msgball_list'])) 3887 { 3888 $this->dbug->out('mail_msg: save_session_cache_item: LEAVING on ERROR, FIXME line '.__LINE__.' we have no msgball_list<br />'); 3889 echo 'mail_msg: save_session_cache_item: LEAVING on ERROR, FIXME line '.__LINE__.' we have no msgball_list<br />'; 3890 // LEAVING ERROR 3891 return False; 3892 } 3893 3894 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): $data_name ['.$data_name.'] is saved with validity data from "get_folder_status_info" for later staleness testing<br />'); } 3895 3896 // NOTE 1: if you provide this 1 thing: 3897 // data['msgball_list'] 3898 // the rest will be filled in for you based on current folder and account (as determined above via acctnum param or the current acctnum arg) 3899 3900 // NOTE 2: if you provide these 2 things 3901 // data['msgball_list'] 3902 // data['validity']['fldball'] 3903 // the "folder_status_info" will be filled in for you SPECIFICALLY for that fldball EVEN IF it is not the current folder or account 3904 3905 // NOTE 3: if you provide these 2 things 3906 // data['msgball_list'] 3907 // data['validity']['folder_status_info'] 3908 // the "fldball" will be filled from your "folder_status_info" which has a fldball data in it 3909 // a FOLDER_STATUS_INFO fldball PREVAILS, it overrules data['validity']['fldball'] 3910 3911 // NOTE 4: if you provide these 3 things 3912 // data['msgball_list'] 3913 // data['validity']['fldball'] 3914 // data['validity']['folder_status_info'] 3915 // then you have provided EVERYTHING we need 3916 3917 // NOTE 5: NOW we also use folder as a data key, so each folder has its own msgball_list 3918 // so later we will use this folder data for what is called $extra_keys, but it is just the folder name here 3919 // update to make it easier to understand I call this $folder_name now 3920 3921 // easy way is "note 1", at this point providing the other stuff is not needed for normal operation 3922 // perhaps if you already have the other stuff and you know it has not changed ("folder_status_info" still good) 3923 // then *maybe* it might save some time passing "folder_status_info" you already have 3924 // if you have many accounts open and the "current account" is hard to discerrn, pass a fldball make sure everything will match 3925 3926 // we need an acctnum, either 3927 // (a) from the fldball, or 3928 // (b) from the fldball in the "folder_status_info", or 3929 // (c) what was passed as the acctnum (which itself is optional, then it will be the "current acctnum" 3930 3931 // we use folder_info for validity testing of data "stale" or not when we retrieve the cached data later 3932 // either data has INCLUDED with it a fldball or we make one based on current account info 3933 if ((isset($data['validity']['folder_status_info']['fldball']['folder']) == True) 3934 && ((string)$data['validity']['folder_status_info']['fldball']['folder'] != '') 3935 && ((string)$data['validity']['folder_status_info']['fldball']['acctnum'] != '')) 3936 { 3937 // folder_status_info IF PROVIDED has PRIORITY of fldball and therefor PRIORITY of acctnum 3938 $acctnum = $data['validity']['folder_status_info']['fldball']['acctnum']; 3939 // make a fldball, ADD IT TO DATA 3940 $data['validity']['fldball'] = array(); 3941 $data['validity']['fldball']['acctnum'] = $acctnum; 3942 $data['validity']['fldball']['folder'] = $data['validity']['folder_status_info']['fldball']['folder']; 3943 } 3944 elseif ((isset($data['validity']['fldball']['folder']) == True) 3945 && ((string)$data['validity']['fldball']['folder'] != '') 3946 && ((string)$data['validity']['fldball']['acctnum'] != '')) 3947 { 3948 // the next place to look for acctnum is here 3949 $acctnum = $data['validity']['fldball']['acctnum']; 3950 // in this case WE CAN NOT RELY on folder_status_info if provided because it is not complete 3951 if (isset($data['validity']['folder_status_info']) == True) 3952 { 3953 $data['validity']['folder_status_info'] == array(); 3954 unset($data['validity']['folder_status_info']); 3955 } 3956 } 3957 else 3958 { 3959 // fallback: using genericly obtained acctnum, make a fldball and add it to DATA 3960 $data['validity']['fldball'] = array(); 3961 $data['validity']['fldball']['acctnum'] = $acctnum; 3962 $data['validity']['fldball']['folder'] = $this->prep_folder_out($this->get_arg_value('folder', $acctnum)); 3963 // just in case incomplete "folder_status_info" was passed, unset it 3964 if (isset($data['validity']['folder_status_info']) == True) 3965 { 3966 $data['validity']['folder_status_info'] == array(); 3967 unset($data['validity']['folder_status_info']); 3968 } 3969 } 3970 3971 // this is really for backwards compat right now 3972 if (isset($data['validity']['folder_long']) == False) 3973 { 3974 $data['validity']['folder_long'] = $data['validity']['fldball']['folder']; 3975 } 3976 3977 // OK now we know we have a fldball, SO we know we have an ACCTNUM, from now on USE THAT ACCTNUM if calling other functions b4 we save this data 3978 // $extra_keys if provided is enabling new stuff, it was not used before for msgball_list data 3979 // IF it is provided (not yet used) it will probably be a folder name in urlencoded form, but NOT SURE YET 3980 // we know what to do here, so this data "has a handler" 3981 $has_handler = True; 3982 3983 // either data has INCLUDED with it "folder_status_info" or we obtain it based on that fldball 3984 if ((isset($data['validity']['folder_status_info']) == False) 3985 || (!$data['validity']['folder_status_info'])) 3986 { 3987 // obtain folder stats, ADD IT TO DATA 3988 $data['validity']['folder_status_info'] = array(); 3989 $data['validity']['folder_status_info'] = $this->get_folder_status_info($data['validity']['fldball']); 3990 } 3991 // ADDITIONAL info that we need for validity testing when we later want to read this info 3992 // ADD IT IF NOT PROVIDED 3993 if (isset($data['validity']['sort']) == False) 3994 { 3995 $data['validity']['sort'] = $this->get_arg_value('sort', $data['validity']['fldball']['acctnum']); 3996 } 3997 if (isset($data['validity']['order']) == False) 3998 { 3999 $data['validity']['order'] = $this->get_arg_value('order', $data['validity']['fldball']['acctnum']); 4000 } 4001 if ((isset($data['validity']['mailsvr_callstr']) == False) 4002 || (isset($data['validity']['mailsvr_account_username']) == False)) 4003 { 4004 // these two things are REALLY linked together, the better be obtained as a pair 4005 $data['validity']['mailsvr_callstr'] = $this->get_arg_value('mailsvr_callstr', $data['validity']['fldball']['acctnum']); 4006 $data['validity']['mailsvr_account_username'] = $this->get_arg_value('mailsvr_account_username', $data['validity']['fldball']['acctnum']); 4007 } 4008 4009 // only is admin is using DB as session store, if "php4" session is used instead, this is not necessary 4010 //if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4011 //&& (strstr($data['validity']['mailsvr_callstr'] ,'{')) ) 4012 //{ 4013 // // NOTE: YOU BETTER BASE64 ENCODE "DEFANG" the "mailsvr_callstr" OR RISK b0rking your database!!! 4014 // // applies to DBs where ' " / \ and other offensive chars are not handled at the api level in phpgw 4015 // $data['validity']['mailsvr_callstr'] = base64_encode($data['validity']['mailsvr_callstr']); 4016 // // COMMENT THAT OUT if you can prove that DBs are immune to this b0rking 4017 //} 4018 4019 // we have ALL the data we need now 4020 // RECAST DATA ready for saving in appsession 4021 //$data = serialize($data); 4022 4023 // NOW WE USE FOLDER INFO TOO SO EVERY FOLDER GETS ITS OWN MSGBALL_LIST 4024 $folder_name = $data['validity']['fldball']['folder']; 4025 if (($this->debug_session_caching > 2) && ($this->debug_allow_magball_list_dumps)) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.']['.$folder_name.'] DUMP:', $data); } 4026 // SET DATA 4027 //$this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] = $data; 4028 // SET DATA USING FOLDER ALSO 4029 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$folder_name] = $data; 4030 4031 // for DB sessions_db ONLY 4032 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4033 || ($this->use_private_table == True)) 4034 { 4035 //$my_location = (string)$acctnum.';'.$data_name; 4036 // SET DATA USING FOLDER ALSO 4037 $my_location = (string)$acctnum.';'.$data_name.';'.$folder_name; 4038 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to put data into database anglemail table, $my_location ['.$my_location.']<br />'); } 4039 if ($this->use_private_table == True) 4040 { 4041 //$this->so->so_set_data($my_location, $data); 4042 // TRY USING COMPRESSION 4043 $this->so->so_set_data($my_location, $data, True); 4044 } 4045 else 4046 { 4047 // NOTE compression not available for appsession table 4048 $GLOBALS['phpgw']->session->appsession($my_location, 'email', $data); 4049 } 4050 } 4051 4052 $data = array(); 4053 unset($data); 4054 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did SET data for location: [email][dat][$acctnum][$data_name][$extra_keys] :: [email][dat]['.$acctnum.']['.$data_name.']['.$folder_name.'] <br />'); } 4055 return True; 4056 } 4057 // DEFANG special handler for data that might b0rk a database, stuff like ' " / \ and maybe some others, only "mailsvr_callstr" needs this right now 4058 elseif ($data_name == 'mailsvr_callstr_OLD_HANDLER') 4059 //elseif ($data_name == 'mailsvr_callstr') 4060 { 4061 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): session_cache_enabled and DEFANG because $GLOBALS[phpgw_info][server][sessions_type] is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] and data exists for "'.$data_name.'" AND has a handler *here* because phpgw db code may be sensitive to the chars in this data.<br />'); } 4062 // we know what to do here, so this data "has a handler" 4063 $has_handler = True; 4064 //$location = 'acctnum='.(string)$acctnum.';data_name='.$data_name.$extra_keys; 4065 //$app = 'email'; 4066 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): "'.$data_name.'" before encoding: '.serialize($data).'<br />'); } 4067 // DATABASE DEFANG, this item has "database unfriendly" chars in it so we encode it before it goes to appsession cache 4068 $data = base64_encode($data); 4069 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): "'.$data_name.'" AFTER encoding: '.serialize($data).'<br />'); } 4070 4071 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.'] DUMP:', $data); } 4072 // SET DATA 4073 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] = $data; 4074 $data = array(); 4075 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did SET data for location: [email][dat][$acctnum][$data_name] :: [email][dat]['.$acctnum.']['.$data_name.'] <br />'); } 4076 unset($data); 4077 return True; 4078 } 4079 // ANYTHING that is non extreme-mode cachable that requires NO special treatment, add it to this block here 4080 elseif (($data_name == 'mailsvr_namespace') 4081 || ($data_name == 'folder_list') 4082 || ($data_name == 'mailsvr_callstr')) 4083 { 4084 // note "mailsvr_callstr" is handled here is php4 session is used, because no "defanging" is necessary since data does not go into a database via the phpgw api 4085 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): session_cache_enabled and data exists for "'.$data_name.'" AND has a handler<br />'); } 4086 // we know what to do here, so this data "has a handler" 4087 $has_handler = True; 4088 //$location = 'acctnum='.(string)$acctnum.';data_name='.$data_name.$extra_keys; 4089 //$app = 'email'; 4090 // NO CHANGE TO INPUT DATA NECESSARY because the data is in ready to save form 4091 4092 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.'] DUMP:', $data); } 4093 // SET DATA 4094 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] = $data; 4095 // session_db backwards_compat 4096 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4097 || ($this->use_private_table == True)) 4098 { 4099 $my_location = (string)$acctnum.';'.$data_name; 4100 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to put data into phpgw_app_sessions table, $my_location ['.$my_location.']<br />'); } 4101 if ($this->use_private_table == True) 4102 { 4103 $this->so->so_set_data($my_location, $data); 4104 } 4105 else 4106 { 4107 $GLOBALS['phpgw']->session->appsession($my_location, 'email', $data); 4108 } 4109 } 4110 4111 $data = array(); 4112 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did SET data for location: [email][dat][$acctnum][$data_name] :: [email][dat]['.$acctnum.']['.$data_name.'] <br />'); } 4113 unset($data); 4114 return True; 4115 } 4116 else 4117 { 4118 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): in non-extreme mode block, $data_name ['.$data_name.'] has no handler, so Your data better be handled in the extreme mode block or you are SOL!<br />'); } 4119 } 4120 4121 // 2nd -- "session_cache_extreme" stuff, ADDITIONAL EXTRA CACHED ITEMS 4122 if ($this->session_cache_extreme == False) 4123 { 4124 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, return False, because $this->session_cache_extreme='.serialize($this->session_cache_extreme).', so the extra "extreme cache" stuff can NOT use the appsession cache.<br />'); } 4125 return False; 4126 } 4127 elseif ($data_name == 'folder_status_info') 4128 { 4129 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): (extreme-mode) data exists for "'.$data_name.'" AND has a handler<br />'); } 4130 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): "'.$data_name.'" ARRIVING param $data as it is passed into this function DUMP:', $data); } 4131 // DATA REQUIRING "extra_keys" because it is probably one element of a larger group of related data 4132 // we will not waste time making a sub array, instead we add the "extra_keys" to the "location" 4133 // that way we can directly access this individual datUM without the hastle of a sub array 4134 4135 /*! 4136 @capability folder_status_info appsession cached when using extreme-mode 4137 @syntax Data Param ARRIVES to this function like this 4138 folder_status_info $data param arrives into this function like this: 4139 $folder_status_info = $data; 4140 because folder_status_info has in it a fldball item we can use 4141 $folder_status_info[foldball] 4142 has the fldball data we can use that already provided 4143 4144 @discussion The "extra_keys" string is the extra KEY which is "FOLDER" 4145 where "FOLDER" is the "long" foldername, meaning it has the Namespace_Delimiter prefixing it. 4146 NOTE this is less info than some other data items use in their "extra_keys", other data 4147 may require extra_keys that is "FOLDER_UID" where UID is the message UID, but this 4148 data is for "folder_status_info" so no message UID is necessary, nor applicable, to this. 4149 That "extra_keys" string is used in the "location" param of the appsession to access this specific data 4150 which is part of a larger set of data, BUT we do not need to use sub array because that single KEY 4151 will let us directly access this data. 4152 */ 4153 4154 if (!$extra_keys) 4155 { 4156 // (a) make the key, value pair that we will add to the cache 4157 // EXTRA_KEYS = FOLDERNAME_MSGNUM 4158 // we know the acctnum, so we already know the username and server name is correct 4159 // but within that account there are many folders, all data for those folders is indexed by a unique KEY 4160 // by using KEY of msgnum and foldername, we know everything we need to identify the exact data we need 4161 4162 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item: ('.__LINE__.') ['.$data_name.'] needs folder stats to have a PLAIN (not urlencoded) "folder" value ['.$data[$data_name]['folder'].'] so we can urlencode it to make the $specific_key<br />'); } 4163 // $data has info to generate out specific key 4164 // KEY MUST BE FOLDER IN URLENCODED FORM 4165 //$specific_key = $this->prep_folder_out($data[$data_name]['folder']); 4166 // **************** 4167 // fix this data structure, i.e. it should arrive here as one thing and we get the folder from IT itself 4168 // just a temp hack while fixing other stuff 4169 // IS THIS FOLDER NAME ALREADY URLENCODED? IT SHOULD BE. 4170 // but we are only using it as a "extra_keys" so maybe just be consistant with the other data? 4171 //$extra_keys = urlencode($data['folder_status_info']['fldball']['folder']); 4172 //$extra_keys = $data['folder_status_info']['fldball']['folder']; 4173 $extra_keys = $data['fldball']['folder']; 4174 4175 } 4176 // we know what to do here, so this data "has a handler" 4177 $has_handler = True; 4178 4179 // RECAST DATA ready for saving in appsession 4180 //$data = serialize($data); 4181 4182 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.']['.$extra_keys.'] DUMP:', $data); } 4183 // SET DATA 4184 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$extra_keys] = $data; 4185 // for DB sessions_db ONLY 4186 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4187 || ($this->use_private_table == True)) 4188 { 4189 $my_location = (string)$acctnum.';'.$data_name.';'.$extra_keys; 4190 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to put data into phpgw_app_sessions table, $my_location ['.$my_location.']<br />'); } 4191 if ($this->use_private_table == True) 4192 { 4193 $this->so->so_set_data($my_location, $data); 4194 } 4195 else 4196 { 4197 $GLOBALS['phpgw']->session->appsession($my_location, 'email', $data); 4198 } 4199 } 4200 $data = array(); 4201 unset($data); 4202 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did SET data for location: [email][dat][$acctnum][$data_name][$extra_keys] :: [email][dat]['.$acctnum.']['.$data_name.']['.$extra_keys.'] <br />'); } 4203 return True; 4204 } 4205 elseif (($data_name == 'msg_structure') 4206 || ($data_name == 'phpgw_header')) 4207 { 4208 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): (extreme-mode) data exists for "'.$data_name.'" AND has a handler<br />'); } 4209 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): "'.$data_name.'" ARRIVING param $data as it is passed into this function DUMP:', $data); } 4210 // DATA REQUIRING "extra_keys" because it is probably one element of a larger group of related data 4211 // we will not waste time making a sub array, instead we add the "extra_keys" to the "location" 4212 // that way we can directly access this individual datUM without the hastle of a sub array 4213 4214 // "flat_pgw_struct" also known as "part_nice" 4215 4216 /*! 4217 @capability msg_structure and phpgw_header unique handling 4218 @abstract The theory is correct and still applied, but the sub-array style is OLD OLD OLD 4219 and has been changed to "extra_keys" in the "location" 4220 @discussion These 2 data items are cached ONLY IF this->session_cache_extreme IS TRUE. 4221 Notes on this data caching (see 4 notes, 2 in discussion and 2 in syntax): 4222 (1) Fetchstructure data can ONLY BE OBTAINED for the currently selected folder, 4223 so we automatically know which folder this data is applies to by calling get_arg_value("folder") 4224 HOWEVER in order to break free from this limitation in grabbing the data we are about to cache, 4225 ALWAYS pass a msgball WITH a folder value, even though it is obvious now, it may not be later. 4226 Note: folder name must be in urlencoded form, because it may contain "database unfriendly" chars 4227 This applies to "phpgw_header" data also. 4228 (Note: a msgball without a folder is *extremely* rare, and probably never occurs.) 4229 (2) "msg_structure" and "phpgw_header" caching scheme is UNUSUAL because 4230 it requires "extra_keys" param with BOTH folder AND message UID. 4231 You can provide such an "extra_keys" param BUT that is NOT necessary because we will make 4232 the "extra_keys" string here, using the data from the "msgball" element of the data structure, 4233 see "syntax" below for how you MUST pass data into this function to save this data type. 4234 @syntax (3) The "extra_keys" string is the extra KEY which is "FOLDER_UID" 4235 where "FOLDER" is the "long" foldername, meaning it has the Namespace_Delimiter prefixing it, and 4236 where "_" is an underscore char, and 4237 where "UID" is the msgnum UID that the mailserver has given the message. 4238 That "extra_keys" string is used in the "location" param of the appsession to access this specific data 4239 which is part of a larger set of data, BUT we do not need to use sub array because that single KEY 4240 will let us directly access this data. 4241 4242 (4) Data Param ARRIVES to this function like this 4243 msg_structure $data param arrives into this function like this: 4244 $data['msgball'] = $msgball; 4245 $data['msg_structure'] = $data; 4246 4247 phpgw_header $data param arrives into this function like this: 4248 $data['msgball'] = $msgball; 4249 $data['phpgw_header'] = $data; 4250 @author Angles 4251 */ 4252 4253 if (!$extra_keys) 4254 { 4255 // (a) make the key, value pair that we will add to the cache 4256 // EXTRA_KEYS = FOLDERNAME_MSGNUM 4257 // we know the acctnum, so we already know the username and server name is correct 4258 // but within that account there are many folders, all data for those folders is indexed by a unique KEY 4259 // by using KEY of msgnum and foldername, we know everything we need to identify the exact data we need 4260 4261 //$extra_keys = (string)$data['msgball']['msgnum'].'_'.$data['msgball']['folder']; 4262 // OLD WAY -- DEPRECIATED 4263 $extra_keys = $data['msgball']['folder'].'_'.(string)$data['msgball']['msgnum']; 4264 } 4265 // NEW METHOD -- USE THIS 4266 $ex_folder = $data['msgball']['folder']; 4267 $ex_msgnum = $data['msgball']['msgnum']; 4268 // we know what to do here, so this data "has a handler" 4269 $has_handler = True; 4270 4271 // RECAST DATA ready for saving in appsession 4272 //$data = serialize($data[$data_name]); 4273 $data = $data[$data_name]; 4274 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.'] DUMP:', $data); } 4275 // SET DATA 4276 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum] = $data; 4277 // for DB sessions_db ONLY 4278 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4279 || ($this->use_private_table == True)) 4280 { 4281 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder.';'.$ex_msgnum; 4282 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to put data into phpgw_app_sessions table, $my_location ['.$my_location.']<br />'); } 4283 if ($this->use_private_table == True) 4284 { 4285 $this->so->so_set_data($my_location, $data); 4286 } 4287 else 4288 { 4289 $GLOBALS['phpgw']->session->appsession($my_location, 'email', $data); 4290 } 4291 } 4292 $data = array(); 4293 unset($data); 4294 //if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did SET data for location: [email][dat][$acctnum][$data_name][$ex_folder][$ex_msgnum] :: [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.'] <br />'); } 4295 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did SET data for [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.'] <br />'); } 4296 return True; 4297 } 4298 elseif ($data_name == 'phpgw_fetchbody') 4299 { 4300 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): (extreme-mode) data exists for "'.$data_name.'" AND has a handler<br />'); } 4301 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): "'.$data_name.'" ARRIVING param $data as it is passed into this function DUMP:', $data); } 4302 4303 //(1) Data Param ARRIVES to this function like this 4304 //msg_structure $data param arrives into this function like this: 4305 // $data['msgball'] = $msgball; 4306 // $data['phpgw_fetchbody'] = $data; 4307 // 4308 //(2) Data Param $data['msgball'] SHOULD HAVE ELEMENT "part_no" !!!! 4309 // $data['msgball']['acctnum'] 4310 // $data['msgball']['folder'] 4311 // $data['msgball']['msgnum'] 4312 // $data['msgball']['part_no'] 4313 4314 if ((!isset($data['msgball']['part_no'])) 4315 || (!$data['msgball']['part_no'])) 4316 { 4317 // LEAVING 4318 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING with ERROR, returning FALSE, insufficient data for ['.$data_name.'] because NOT GIVEN $data[msgball][part_no]; $data[msgball] was ['.serialize($data['msgball']).'] <br />'); } 4319 return False; 4320 } 4321 $strlen_phpgw_fetchbody = strlen($data['phpgw_fetchbody']); 4322 if ($strlen_phpgw_fetchbody > 60000) 4323 { 4324 // LEAVING 4325 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING with ERROR, returning FALSE, data TOO LARGE for ['.$data_name.']; $strlen_phpgw_fetchbody; $data[msgball] was ['.$strlen_phpgw_fetchbody.'] <br />'); } 4326 return False; 4327 } 4328 4329 $ex_folder = $data['msgball']['folder']; 4330 $ex_msgnum = $data['msgball']['msgnum']; 4331 $ex_part_no = $data['msgball']['part_no']; 4332 // we know what to do here, so this data "has a handler" 4333 $has_handler = True; 4334 4335 // RECAST DATA ready for saving in appsession 4336 //$data = serialize($data[$data_name]); 4337 $data = $data[$data_name]; 4338 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.']['.$ex_part_no.'] DUMP:', $data); } 4339 // SET DATA 4340 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no] = $data; 4341 // for DB sessions_db ONLY 4342 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4343 || ($this->use_private_table == True)) 4344 { 4345 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder.';'.$ex_msgnum.';'.$ex_part_no; 4346 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): AM Table in use or sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to put data into a table table, $my_location ['.$my_location.'], this is always needed for AM table<br />'); } 4347 if ($this->use_private_table == True) 4348 { 4349 $this->so->so_set_data($my_location, $data); 4350 } 4351 else 4352 { 4353 $GLOBALS['phpgw']->session->appsession($my_location, 'email', $data); 4354 } 4355 } 4356 $data = array(); 4357 unset($data); 4358 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did SET data for [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.']['.$ex_part_no.'] <br />'); } 4359 return True; 4360 } 4361 else 4362 { 4363 // this data_name has no specific handler 4364 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): NOTE: no handler for data_name='.$data_name.' in extreme-mode block<br />'); } 4365 //echo 'mail_msg: save_session_cache_item('.__LINE__.'): LEAVING with ERROR: NO HANDLER for data_name='.$data_name.' in extreme-mode block, DATA WILL NOT BE SAVED, returning False<br />'; 4366 // LEAVING 4367 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: save_session_cache_item('.__LINE__.'): LEAVING with ERROR, no data handler for: [email][dat][$acctnum][$data_name][$extra_keys] :: [email][dat]['.$acctnum.']['.$data_name.']['.$extra_keys.'] <br />'); } 4368 return False; 4369 } 4370 4371 /* 4372 // save data, assuming we've "handled" it 4373 // perhaps we already saved and exited above, or even exited on error above 4374 if ((isset($data) == True) 4375 && ($has_handler == True)) 4376 { 4377 if ($this->debug_session_caching > 1) { echo 'mail_msg: save_session_cache_item('.__LINE__.'): location: ['.$location.'] $app='.$app.'; $meta dump:<pre>'; print_r($data); echo '</pre>'; } 4378 if ($this->session_cache_debug_nosave == False) 4379 { 4380 $GLOBALS['phpgw']->session->appsession($location,$app,$data); 4381 } 4382 else 4383 { 4384 echo 'mail_msg: save_session_cache_item('.__LINE__.'): session_cache_debug_nosave disallows actual saving of data<br />'; 4385 } 4386 if ($this->debug_session_caching > 0) { echo 'mail_msg: save_session_cache_item('.__LINE__.'): LEAVING, did set data for $data_name ['.$data_name.'] $acctnum ['.$acctnum.'], returning True<br />'; } 4387 return True; 4388 } 4389 else 4390 { 4391 if ($this->debug_session_caching > 0) { echo 'mail_msg: save_session_cache_item('.__LINE__.'): LEAVING on ERROR, no handler for $data_name ['.$data_name.'] $acctnum ['.$acctnum.'], OR data was empty AFTER we messed with, we screwed it up? returning False<br />'; } 4392 return False; 4393 } 4394 */ 4395 } 4396 4397 4398 /*! 4399 @function read_session_cache_item BEING OVERHAULED preliminary complete. 4400 @abstract get data from the appsession cache, requires a "handler" to be in this function to return the desired data. 4401 @param $data_name (string) The name of the data you want from the appsession cache, needs a handler in this function to return it. 4402 @param $acctnum (int) optional, can pass as an empty string the this function will use the currently active account. 4403 However, if you are not doiung the usual "show X msgs in a folder", such as showing search results from multiple 4404 sources, then there really is no "currently active" acctnum so you SHOULD pass it in that case. 4405 @param $ex_folder (string) folder name, in "preped_out" urlencoded form, the data applies to, such as for restoring "folder_status_info" 4406 @param $ex_msgnum (int) msgnum data applies to, currently only needed for restoring "msg_structure" and "phpgw_header" data 4407 which of course need the $ex_folder param too, any data requiring this $ex_msgnum param also requires the $ex_folder param. 4408 @author Angles 4409 @discussion used with appsession TEMPORARY DATA CACHING server-side caching of limited, 4410 ephermal data, such as a list of messages from an imap search, via appsession. 4411 NOTE: currently only ONE "msgball_list" is saved per account, and when user changes folders 4412 within an account, we must request a new "msgball_list" for that folder from the mail server. 4413 ISSUES (pro) this saves appsession from building up massive lists of msgballs, and (con) this 4414 results in needless requesting of info that we may have already asked for. NOTE the msgball_list 4415 does not care about number new, and only looks at number all to know when to refresh itself. 4416 The primary handler of that status info is function "get_folder_status_info". THEREFOR 4417 msgball_list most important freshness meta_data is "number_all" for what we need to do. 4418 We need to use an event to directly make fresh the cached data and save it back to cache, 4419 so in order for the data not to look "stale" we need to do some math on the "number_all" in 4420 that msgball_list meta_data also. 4421 FURTHER DISCUSSION is that this is a PRIVATE function, generally you ask for a 4422 peice if data with the "get_arg_value" function, or in some cases by calling a specific function 4423 such as "get_msgball_list", then those functions determine HOW you get the data, including 4424 IF the data should be returned from the appsession cache. Therefor, for whatever data you 4425 want, YOU SHOULD NOT DIRECTLY call this function UNLESS YOU REALLY KNOW 4426 what you are doing and you are doing some exotic stuff. 4427 NOTE: ALL INFO SUBJECT TO CHANGE. 4428 @access private 4429 */ 4430 function read_session_cache_item($data_name='misc', $acctnum='', $ex_folder='', $ex_msgnum='', $ex_part_no='') 4431 { 4432 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): ENTERED, $data_name: ['.$data_name.']; optional: $acctnum: ['.$acctnum.'], $ex_folder: ['.$ex_folder.'], $ex_msgnum: ['.$ex_msgnum.'], $ex_part_no: ['.$ex_part_no.'] '.'<br />'); } 4433 if ($this->debug_session_caching > 1) { $this->dbug->out('AND $this->session_cache_enabled='.serialize($this->session_cache_enabled).'; $this->session_cache_extreme='.serialize($this->session_cache_extreme).'<br />'); } 4434 if ($this->debug_session_caching > 0) { $this->dbug->out('<br />'); } 4435 $font_start = '<font color="purple">'; 4436 $font_end = '</font>'; 4437 4438 if ((!isset($acctnum)) 4439 || ((string)$acctnum == '')) 4440 { 4441 $acctnum = $this->get_acctnum(); 4442 } 4443 4444 if ($this->session_cache_enabled == False) 4445 { 4446 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, nothing to do since $this->session_cache_enabled='.serialize($this->session_cache_enabled).' returning False I guess<br />'); } 4447 // EXITING NOW!~!!!!! 4448 return False; 4449 } 4450 4451 // we are here so at least some caching is allowed, get the data from appsession 4452 // handle it accordingly 4453 if (($data_name == 'folder_status_info') 4454 && ($this->session_cache_extreme == True)) 4455 { 4456 // GET DATA 4457 // for DB sessions_db ONLY 4458 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4459 || ($this->use_private_table == True)) 4460 { 4461 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder; 4462 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to read data from phpgw_app_sessions table, $my_location ['.$my_location.']<br />'); } 4463 if ($this->use_private_table == True) 4464 { 4465 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder] 4466 = $this->so->so_get_data($my_location); 4467 } 4468 else 4469 { 4470 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder] 4471 = $GLOBALS['phpgw']->session->appsession($my_location, 'email'); 4472 } 4473 //if ($this->debug_session_caching > 2) { echo 'mail_msg: read_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.'] DUMP:<pre>'; print_r($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder]); echo '</pre>'; } 4474 } 4475 4476 // GET DATA 4477 // "folder_status_info" DATA IS ONLY appsession CACHED IF $this->session_cache_extreme IS TRUE 4478 $folder_status_info = $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder]; 4479 4480 if ($folder_status_info) 4481 { 4482 // HAVE WE ALREADY DONE THE TIMESTAMP CHECK ? 4483 // we only need the timestamp text once 4484 $already_checked_ok = $this->get_isset_arg('["folder_status_info_already_checked_ok"]["'.$ex_folder.'"]', $acctnum); 4485 //$this->get_arg_value('["msgball"]["msgnum"]') 4486 4487 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') location: ['.$location.'] $app='.$app.'; $got_data DUMP:', $got_data); } 4488 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') $data_name ['.$data_name.'], is only cached is $this->session_cache_extreme is TRUE<br />'); } 4489 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') $data_name ['.$data_name.'], timestamp check is SKIPPED if $already_checked_ok is set, $already_checked_ok: ['.serialize($already_checked_ok).']<br />'); } 4490 // this is set as a class param in file mail_msg_base 4491 $timestamp_age_limit = $this->timestamp_age_limit; 4492 4493 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') handler exists for $data_name ['.$data_name.'], this item requires param $extra_keys ['.serialize($extra_keys).']<br />'); } 4494 // this special handler uses timestamp info to determine "freshness" 4495 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') KEY ($special_extra_stuff) MUST BE FED INTO HERE AS A FOLDER IN URLENCODED FORM<br />'); } 4496 //if ($this->debug_session_caching > 1) { echo 'mail_msg: read_session_cache_item: ('.__LINE__.') $data_name ['.$data_name.'], param $special_extra_stuff gives us $specific_key ['.$specific_key.']<br />'; } 4497 //$folder_status_info = unserialize($folder_status_info); 4498 $timestamp_age = (time() - $folder_status_info['timestamp']); 4499 if ($this->debug_session_caching > 1) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') got cached data, $timestamp_age ['.$timestamp_age.'] ; $timestamp_age_limit ['.$timestamp_age_limit.']<br />'); } 4500 if ($this->debug_session_caching > 2) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') $folder_status_info DUMP:', $folder_status_info); } 4501 if ($already_checked_ok == True) 4502 { 4503 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') $data_name ['.$data_name.'], timestamp check will be '.'<font color="red">'.'SKIPPED'.'</font>'.' because we already checked it this page view, $already_checked_ok: ['.serialize($already_checked_ok).']<br />'); } 4504 } 4505 elseif ($timestamp_age > $timestamp_age_limit) 4506 { 4507 if ($this->debug_session_caching > 1) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') LEAVING, $timestamp_age ['.$timestamp_age.'] EXCEEDS $timestamp_age_limit ['.$timestamp_age_limit.'], this data NEEDS REFRESHING, expire this element<br />'); } 4508 $got_data = ''; 4509 unset($got_data); 4510 //$this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder] = array(); 4511 //unset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder]); 4512 // this does the same thing, so use this instead 4513 $this->expire_session_cache_item('folder_status_info', $acctnum, $ex_folder); 4514 4515 if ($this->debug_session_caching > 0) { $this->dbug->out('class_msg: get_folder_status_info: ('.__LINE__.') LEAVING, $data_name ['.$data_name.'] $specific_key ['.$specific_key.'], $timestamp_age ['.$timestamp_age.'] EXCEEDS $timestamp_age_limit ['.$timestamp_age_limit.'], this data NEEDS REFRESHING, returning False<br />'); } 4516 return False; 4517 4518 } 4519 // set flag "folder_status_info_already_checked_ok" for this ex_folder so we do NOT timestamp check again the rest of THIS PAGEVIEW 4520 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') $data_name ['.$data_name.'], set arg ["folder_status_info_already_checked_ok"]['.$ex_folder.'] so we DO NOT timestamp check this data again for the rest of this script run<br />'); } 4521 $this->set_arg_value('["folder_status_info_already_checked_ok"]["'.$ex_folder.'"]', 'timestamp_ok', $acctnum); 4522 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') LEAVING, '.$font_start.'successfully restored ['.$data_name.']'.$font_end.' session data, $acctnum: ['.$acctnum.'], $ex_folder ['.htmlspecialchars($ex_folder).'], data passed timestamp test<br />'); } 4523 return $folder_status_info; 4524 } 4525 else 4526 { 4527 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item: ('.__LINE__.') LEAVING, returning False, $data_name ['.$data_name.'] had NO data stored, $acctnum: ['.$acctnum.'], $ex_folder ['.htmlspecialchars($ex_folder).']<br />'); } 4528 return False; 4529 } 4530 4531 } 4532 elseif ($data_name == 'msgball_list') 4533 { 4534 4535 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handler exists for $data_name ['.$data_name.']<br />'); } 4536 4537 /*! 4538 @capability VERIFY appsession cached "msgball_list" data is still valid (in read_session_cache_item) 4539 @discussion The "msgball_list" is a list of all messages in a folder sorted according to user prefs and 4540 containing additional information to make each message UID into a msgball by adding the acctnum 4541 and folder data to the msgnum. This data is put into a numbered array we call the "msgball_list". 4542 This "msgball_list" is cached in the appsession along with some meta_data that we use verify the 4543 cached msgball_list as (a) applicable to the current mailserver and user, and (b) for "freshness". 4544 For (b) "freshness", we compare the meta_data items for folder status against the 4545 current "folder_status_info" data to determine if this cached msgball_list is "fresh" or "stale". 4546 See the example for the exact data structure of the cached data. Additionally, for (a) "applicablility" 4547 just to be super safe, the cached msgball_list meta_data is tested against the current "mailsvr_callstr" and 4548 the current "mailsvr_account_username" args, not really needed but is does make us confident 4549 that the cached msgball_list applies to the same account as existed when the cache was set. It is not 4550 really known how they could not match, but this additional test can not hurt. 4551 This test is the SAME for session_cache_extreme True or False, 4552 the difference is that for session_cache_extreme TRUE, the "number_all" element 4553 of this data and the "number_all" element of the "folder_status_info" appsession cached 4554 data is manually updated so (1) they are "fresh" with respect to changes the user makes 4555 such as moving or deleting mail from a folder, and (2) so the following test which matches 4556 "number_all" elements of both data sets remain the same, so the "msgball_list" is considered 4557 "fresh" by this test. 4558 @example This is the meta data that is saved and tested on reading the data from cache. 4559 $validity_test['fldball'] = array(); 4560 $validity_test['fldball']['acctnum'] = $acctnum; 4561 $validity_test['fldball']['folder'] = $this->get_arg_value('folder', $acctnum); 4562 $validity_test['folder_status_info']['uidnext'] = $folder_info['uidnext']; 4563 $validity_test['folder_status_info']['uidvalidity'] = $folder_info['uidvalidity']; 4564 $validity_test['folder_status_info']['number_all'] = $folder_info['number_all']; 4565 $validity_test['sort'] = $this->get_arg_value('sort', $acctnum); 4566 $validity_test['order'] = $this->get_arg_value('order', $acctnum); 4567 $validity_test['mailsvr_callstr'] = $this->get_arg_value('mailsvr_callstr', $acctnum); 4568 $validity_test['mailsvr_account_username'] = $this->get_arg_value('mailsvr_account_username', $acctnum); 4569 @author Angles 4570 */ 4571 4572 // NEW: NOW WE NEED A FOLDER NAME TO COMPLETE THE KEY 4573 // if one is not provided as a param, 4574 // (a) WE MUST GET ONE, and 4575 // (b) it must be URLENCODED, or preped_out 4576 if ($ex_folder != '') 4577 { 4578 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handling ['.$data_name.'] we DID get passed param $ex_folder ['.$ex_folder.']<br />'); } 4579 } 4580 else 4581 { 4582 $ex_folder = $this->prep_folder_out($this->get_arg_value('folder', $acctnum)); 4583 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handling ['.$data_name.'] we did NOT get param $ex_folder so we just obtained and set it to this: ['.$ex_folder.']<br />'); } 4584 } 4585 4586 // GET DATA 4587 // for DB sessions_db ONLY 4588 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4589 || ($this->use_private_table == True)) 4590 { 4591 //$my_location = (string)$acctnum.';'.$data_name; 4592 // WE N OW USE FOLDER DATA TOO 4593 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder; 4594 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to read data from a database table, $my_location ['.$my_location.']<br />'); } 4595 if ($this->use_private_table == True) 4596 { 4597 //$got_data = array(); 4598 //$got_data = $this->so->so_get_data($my_location); 4599 //$this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] 4600 // = $got_data; 4601 4602 //$this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] 4603 // = $this->so->so_get_data($my_location); 4604 4605 // TRY USING COMPRESSION 4606 //$this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] 4607 // = $this->so->so_get_data($my_location, True); 4608 4609 // TRY USING COMPRESSION 4610 $got_data = array(); 4611 $got_data = $this->so->so_get_data($my_location, True); 4612 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder] 4613 = $got_data; 4614 } 4615 else 4616 { 4617 // NOTE: no compression available for appsession 4618 $got_data = array(); 4619 $got_data = $GLOBALS['phpgw']->session->appsession($my_location, 'email'); 4620 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder] 4621 = $got_data; 4622 4623 // NOTE: no compression available for appsession 4624 //$this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder] 4625 // = $GLOBALS['phpgw']->session->appsession($my_location, 'email'); 4626 } 4627 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.'] DUMP:', $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder]); } 4628 } 4629 //$got_data = $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name]; 4630 4631 if (($this->debug_session_caching > 2) && ($this->debug_allow_magball_list_dumps)) { $this->dbug->out('mail_msg: read_session_cache_item: $data_name ['.$data_name.'] verified NOT Stale, restored data DUMP:', $got_data); } 4632 if (!$got_data) 4633 { 4634 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, returning False, <font color="red">$data_name ['.$data_name.'] had NO data stored</font>, $acctnum: ['.$acctnum.'], $ex_folder ['.$ex_folder.']<br />'); } 4635 return False; 4636 } 4637 else 4638 { 4639 // folder_info used to test validity (stale or not) of the cached msgball_list data 4640 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handling $data_name ['.$data_name.'] session validity and/or relevance, check against "get_folder_status_info" data<br />'); } 4641 // UPDATE THIS CRAP TO HANDLE ANY FOLDER WITHIN A SINGLE ACCOUNT, not just the current one 4642 $fldball = array(); 4643 $fldball['acctnum'] = $acctnum; 4644 $fldball['folder'] = $this->prep_folder_out($this->get_arg_value('folder', $acctnum)); 4645 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handling ['.$data_name.'] requires obtaining "folder_status_info" we get by calling $this->get_folder_status_info('.serialize($fldball).')<br />'); } 4646 $folder_info = $this->get_folder_status_info($fldball); 4647 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): ['.$data_name.'] will be verified as representing this folder and acctnum, then freshness checked <i>details: with the stored "folder_status_info" compared to the "folder_status_info" we just obtained a few lines up, which "folder_status_info" was itself validated in the function we got it from. The "msgball_list" is appsession cached whether in "extreme-mode" or not, as long as "enable_session_cache" is true </i><br />'); } 4648 4649 // "validity_test" is what the test is like, but it's only really used for the debug data dump 4650 // because the real test below gets all the same info all over again as exists in this "match_to_be_fresh" array 4651 $validity_test = array(); 4652 $validity_test['fldball'] = array(); 4653 $validity_test['fldball']['acctnum'] = $acctnum; 4654 $validity_test['fldball']['folder'] = $this->prep_folder_out($this->get_arg_value('folder', $acctnum)); 4655 $validity_test['folder_status_info']['uidnext'] = $folder_info['uidnext']; 4656 $validity_test['folder_status_info']['uidvalidity'] = $folder_info['uidvalidity']; 4657 $validity_test['folder_status_info']['number_all'] = $folder_info['number_all']; 4658 $validity_test['sort'] = $this->get_arg_value('sort', $acctnum); 4659 $validity_test['order'] = $this->get_arg_value('order', $acctnum); 4660 $validity_test['mailsvr_callstr'] = $this->get_arg_value('mailsvr_callstr', $acctnum); 4661 $validity_test['mailsvr_account_username'] = $this->get_arg_value('mailsvr_account_username', $acctnum); 4662 4663 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): $data_name ['.$data_name.'] validity check, freshness litmus test match this $validity_test DUMP:', $validity_test); } 4664 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): $data_name ['.$data_name.'] validity check, restored data validity $got_data[validity] DUMP:', $got_data['validity']); } 4665 4666 // only is admin is using DB as session store, if "php4" session is used instead, this is not necessary 4667 //if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4668 //&& (!strstr($got_data['validity']['mailsvr_callstr'] ,'{')) ) 4669 //{ 4670 // // NOTE: YOU BETTER BASE64 ENCODE "DEFANG" the "mailsvr_callstr" OR RISK b0rking your database!!! 4671 // // applies to DBs where ' " / \ and other offensive chars are not handled at the api level in phpgw 4672 // $got_data['validity']['mailsvr_callstr'] = base64_decode($got_data['validity']['mailsvr_callstr']); 4673 // // COMMENT THAT OUT if you can prove that DBs are immune to this b0rking 4674 //} 4675 4676 if (($got_data['validity']['fldball']['folder'] == $this->prep_folder_out($this->get_arg_value('folder', $acctnum))) 4677 && ($got_data['validity']['fldball']['acctnum'] == $acctnum) 4678 && ($got_data['validity']['folder_status_info']['uidnext'] == $folder_info['uidnext']) 4679 && ($got_data['validity']['folder_status_info']['uidvalidity'] == $folder_info['uidvalidity']) 4680 && ($got_data['validity']['folder_status_info']['number_all'] == $folder_info['number_all']) 4681 && ($got_data['validity']['sort'] == $this->get_arg_value('sort', $acctnum)) 4682 && ($got_data['validity']['order'] == $this->get_arg_value('order', $acctnum)) 4683 && ($got_data['validity']['mailsvr_callstr'] == $this->get_arg_value('mailsvr_callstr', $acctnum)) 4684 && ($got_data['validity']['mailsvr_account_username'] == $this->get_arg_value('mailsvr_account_username', $acctnum))) 4685 { 4686 if (($this->debug_session_caching > 2) && ($this->debug_allow_magball_list_dumps)) { $this->dbug->out('mail_msg: read_session_cache_item: $data_name ['.$data_name.'] verified NOT Stale, restored data DUMP:', $got_data); } 4687 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, '.$font_start.'successfully restored ['.$data_name.']'.$font_end.' VALID and NOT Stale session data, $acctnum: ['.$acctnum.'] param (or obtained) $ex_folder ['.$ex_folder.']<br />'); } 4688 return $got_data['msgball_list']; 4689 } 4690 else 4691 { 4692 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): EXPIRE STALE ['.$data_name.'] session data for $acctnum: ['.$acctnum.'], $ex_folder ['.$ex_folder.']<br />'); } 4693 //$this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] = array(); 4694 //unset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name]); 4695 // this is better to use 4696 //$this->expire_session_cache_item($data_name, $acctnum); 4697 // NOW WE USE FOLDER IN DATA KEY ALSO 4698 $this->expire_session_cache_item($data_name, $acctnum, $ex_folder); 4699 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, returning False, $data_name ['.$data_name.'] session was STALE, $acctnum: ['.$acctnum.'], $ex_folder ['.$ex_folder.']<br />'); } 4700 return False; 4701 } 4702 } 4703 } 4704 elseif ($data_name == 'mailsvr_callstr_OLD_HANDLER') 4705 //elseif ($data_name == 'mailsvr_callstr') 4706 { 4707 // GET DATA 4708 $got_data = $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name]; 4709 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): DEFANG because session cache is "db", this handler exists for $data_name ['.$data_name.']<br />'); } 4710 // this special handler decodes the database defanging 4711 if ($got_data) 4712 { 4713 // DATABASE DEFANG, this item has "database unfriendly" chars in it so we encode it before it goes to appsession cache 4714 // now we mode DECODE it coming out of the appsession cache 4715 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): restored $data_name ['.$data_name.'] (pre-decoded) data DUMP:', $got_data); } 4716 $got_data = base64_decode($got_data); 4717 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): restored $data_name ['.$data_name.'] (decoded) data DUMP:', $got_data); } 4718 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, '.$font_start.'successfully restored ['.$data_name.']'.$font_end.' session data, $acctnum: ['.$acctnum.'], $extra_keys: ['.$extra_keys.']<br />'); } 4719 return $got_data; 4720 } 4721 else 4722 { 4723 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, returning False, $data_name='.$data_name.' had NO data stored, $acctnum: ['.$acctnum.'], $extra_keys: ['.$extra_keys.']<br />'); } 4724 return False; 4725 } 4726 } 4727 elseif (($data_name == 'mailsvr_namespace') 4728 || ($data_name == 'folder_list') 4729 || ($data_name == 'mailsvr_callstr')) 4730 { 4731 // GET DATA 4732 // for DB sessions_db ONLY 4733 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4734 || ($this->use_private_table == True)) 4735 { 4736 $my_location = (string)$acctnum.';'.$data_name; 4737 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to read data from phpgw_app_sessions table, $my_location ['.$my_location.']<br />'); } 4738 if ($this->use_private_table == True) 4739 { 4740 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] 4741 = $this->so->so_get_data($my_location); 4742 } 4743 else 4744 { 4745 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] 4746 = $GLOBALS['phpgw']->session->appsession($my_location, 'email'); 4747 } 4748 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.'] DUMP:', $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name]); } 4749 } 4750 $got_data = $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name]; 4751 4752 // "mailsvr_callstr" if session is NOT "db" is handled here because no database defang if necessary 4753 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handler exists for $data_name ['.$data_name.']<br />'); } 4754 // this is not really a special handler 4755 if ($got_data) 4756 { 4757 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): restored $data_name ['.$data_name.'] data DUMP:', $got_data); } 4758 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, '.$font_start.'successfully restored ['.$data_name.']'.$font_end.' session data, $acctnum: ['.$acctnum.'], $extra_keys: ['.$extra_keys.']<br />'); } 4759 return $got_data; 4760 } 4761 else 4762 { 4763 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, returning False, $data_name ['.$data_name.'] had NO data stored, $acctnum: ['.$acctnum.'], $extra_keys: ['.$extra_keys.']<br />'); } 4764 return False; 4765 } 4766 4767 } 4768 elseif (($this->session_cache_extreme == True) 4769 && ( 4770 ($data_name == 'msg_structure') 4771 || ($data_name == 'phpgw_header')) 4772 ) 4773 { 4774 // THIS DATA IS NEVER CACHED IF $this->session_cache_extreme IS FALSE 4775 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handler exists for $data_name ['.$data_name.']<br />'); } 4776 // this IS a special handler because we do not return the entire cached array of "msg_structure" elements, 4777 // we only return ONE SINGLE "msg_structure" (or "phpgw_header" ) value from that array, 4778 // if it exists in that array. 4779 // the array can exist but not have the specific element we are looking for 4780 // NOTE: we need param $special_extra_stuff because other cached items are returned whole 4781 // but "msg_structure" (or "phpgw_header" ) need that EXTRA peice of information 4782 // to return only a portion of cached data. 4783 4784 // GET DATA 4785 // for DB sessions_db ONLY 4786 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4787 || ($this->use_private_table == True)) 4788 { 4789 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder.';'.$ex_msgnum; 4790 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to read data from phpgw_app_sessions table, $my_location ['.$my_location.']<br />'); } 4791 if ($this->use_private_table == True) 4792 { 4793 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum] 4794 = $this->so->so_get_data($my_location); 4795 } 4796 else 4797 { 4798 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum] 4799 = $GLOBALS['phpgw']->session->appsession($my_location, 'email'); 4800 } 4801 //if ($this->debug_session_caching > 2) { echo 'mail_msg: read_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.'] ['.$ex_msgnum.']DUMP:<pre>'; print_r($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum]); echo '</pre>'; } 4802 } 4803 $got_data = $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum]; 4804 4805 if ($got_data) 4806 { 4807 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): found an existing array of items for $data_name ['.$data_name.'] data DUMP:', $got_data); } 4808 // we need more info than the usual cached item to get what we want, because we want a SINGLE element only 4809 // the array KEY in the key,value pair is passed in param $special_extra_stuff 4810 4811 // SUCCESS - desired single element within that array does exist 4812 // also unserialize it back into an object 4813 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, '.$font_start.'successfully restored ['.$data_name.']'.$font_end.' session data for [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.']<br />'); } 4814 // NOTE unserializing an already inserialized thing gives you NOTHING, so damn well better serialize this on saving to the appsession cache. 4815 return $got_data; 4816 4817 } 4818 } 4819 elseif (($this->session_cache_extreme == True) 4820 && ($data_name == 'phpgw_fetchbody')) 4821 { 4822 // THIS DATA IS NEVER CACHED IF $this->session_cache_extreme IS FALSE 4823 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): handler exists for $data_name ['.$data_name.']<br />'); } 4824 4825 // GET DATA 4826 // for DB sessions_db ONLY 4827 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4828 || ($this->use_private_table == True)) 4829 { 4830 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder.';'.$ex_msgnum.';'.$ex_part_no; 4831 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): AM table in use or sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to read data from a table table, $my_location ['.$my_location.']<br />'); } 4832 if ($this->use_private_table == True) 4833 { 4834 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no] 4835 = $this->so->so_get_data($my_location); 4836 } 4837 else 4838 { 4839 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no] 4840 = $GLOBALS['phpgw']->session->appsession($my_location, 'email'); 4841 } 4842 //if ($this->debug_session_caching > 2) { echo 'mail_msg: read_session_cache_item('.__LINE__.'): [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.'] ['.$ex_msgnum.']DUMP:<pre>'; print_r($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no]); echo '</pre>'; } 4843 } 4844 $got_data = $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no]; 4845 4846 if ($got_data) 4847 { 4848 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): found an existing array of items for $data_name ['.$data_name.'] data DUMP:', $got_data); } 4849 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, '.$font_start.'successfully restored ['.$data_name.']'.$font_end.' session data for [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.']['.$ex_part_no.']<br />'); } 4850 return $got_data; 4851 4852 } 4853 else 4854 { 4855 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING, returning False, $data_name ['.$data_name.'] had NO data stored, $acctnum: ['.$acctnum.'], $extra_keys: ['.$extra_keys.']<br />'); } 4856 return False; 4857 } 4858 } 4859 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: read_session_cache_item('.__LINE__.'): LEAVING with ERROR, NO SPECIAL HANDLER exists for $data_name ['.$data_name.']<br />'); } 4860 //return $got_data; 4861 return False; 4862 } 4863 4864 /*! 4865 @function expire_session_cache_item BEING OVERHAULED preliminary complete. 4866 @abstract ? 4867 @discussion used with appsession TEMPORARY DATA CACHING server-side caching of limited, 4868 ephermal data, such as a list of messages from an imap search, via appsession 4869 NOTE we get the old data, if any, to see whether it was an array or string, HOWEVER using get_arg_value 4870 for "folder_list" WILL ATTEMPT A LOGIN so to avoid that we use "_direct_access_arg_value" instead. 4871 @author Angles 4872 @access private 4873 */ 4874 // ---- session-only data cached to appsession ---- 4875 function expire_session_cache_item($data_name='misc',$acctnum='', $ex_folder='', $ex_msgnum='', $ex_part_no='') 4876 { 4877 if ((!isset($acctnum)) 4878 || ((string)$acctnum == '')) 4879 { 4880 $acctnum = $this->get_acctnum(); 4881 } 4882 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): ENTERED, $this->session_cache_enabled='.serialize($this->session_cache_enabled).', $data_name: ['.$data_name.'], $acctnum (optional): ['.$acctnum.'], $extra_keys: ['.$extra_keys.']<br />'); } 4883 // process $extra_keys input 4884 4885 // BEFORE we do anything else, if extreme-mode is OFF then we MANDATORY, ALWAYS, NO-MATTER-WHAT expire "folder_status_info" 4886 // NOTE: in non-extreme cache mode, "folder_status_info" is exipred ALLWAYS whenever we expire ANYTHING 4887 // why? because I'm assuming (correctly?) that if we are expiring something then it *probably* effects "folder_status_info" too 4888 // NOTE also that in extreme mode, "folder_status_info" is NOT put in L1 cache EVER, we directly use appsession. 4889 if ($this->session_cache_extreme == False) 4890 { 4891 // --- get rid of any L1 cache for "folder_status_info" --- 4892 if ($this->debug_session_caching > 1) { $this->dbug->out('class_msg: expire_session_cache_item('.__LINE__.'): non-extreme mode ALWAYS EXPIRES "folder_status_info" with ANYTHING ELSE, because non-extreme mode uses "folder_status_info" L1/class var cache only, NO appsession cache used in non-extreme <br />'); } 4893 if ($this->debug_session_caching > 1) { $this->dbug->out('class_msg: expire_session_cache_item('.__LINE__.'): NOTE non-extreme mode uses "folder_status_info" L1/class var cache only, NO appsession cache used in non-extreme <br />'); } 4894 // cache data in a class var (L1 Cache) 4895 // ALWAYS expire "folder_status_info" because many time this expire function is called because of a message move or delete 4896 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): (non-extreme mode) Mandatory clearing of L1 cache/class data "folder_status_info" <br />'); } 4897 $empty_array = array(); 4898 //$this->set_arg_value('folder_status_info', $empty_array, $acctnum); 4899 $this->set_arg_value('["folder_status_info"]["'.$ex_folder.'"]', $empty_array, $acctnum); 4900 4901 } 4902 4903 // now eliminate the EXPIRED data, 1st get rid of any L1 cache it it exists for this item 4904 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): checking for L1 cache/class var for $data_name = ['.$data_name.']<br />'); } 4905 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): NOTE when session_class_extreme is True, "folder_status_info" is NOT cached in L1 cache/class var, only in appsession<br />'); } 4906 4907 // FIRST -- EXPIRE ANY L1 CACHE for this data_name 4908 if (($this->get_isset_arg($data_name, $acctnum)) 4909 && (strstr($data_name, 'folder_status_info') == False)) 4910 { 4911 // NOTE L1 cached "folder_status_info" was (a) expired above for non-extreme mode and (b) never uses L1 cached in extreme mode 4912 //$old_content = $this->get_arg_value($data_name, $acctnum); 4913 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): does L1 cache/class for ['.$data_name.'], to find out we call "_direct_access_arg_value" <b>THUS FOLDER_LIST WILL NOT CAUSE A LOGIN</b> using "get_arg_value" for folder_list WILL ATTEMPT A LOGIN!<br />'); } 4914 $old_content = $this->_direct_access_arg_value($data_name, $acctnum); 4915 if ($this->debug_session_caching > 2) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): found and clearing L1 cache/class for ['.$data_name.'] OLD value DUMP:', $old_content); } 4916 if (gettype($old_content) == 'array') 4917 { 4918 $empty_data = array(); 4919 } 4920 else 4921 { 4922 $empty_data = ''; 4923 } 4924 // set the arg item to this blank value, effectively clearing/expiring it 4925 $this->set_arg_value($data_name, $empty_data, $acctnum); 4926 } 4927 4928 // SECOND -- EXPIRE ANY APPSESSION CACHE for this data_name 4929 // --- now get rid of any "$data_name" value saved in the session cache --- 4930 // also note that in extreme mode we expire "folder_status_info" here because 4931 // (a) it would be handled above for non-extreme mode and 4932 // (b) it uses subitems so we need to handle it here so we expire single sub item and not the whole thing 4933 4934 // DELETE DATA 4935 // for DB sessions_db ONLY 4936 if (($GLOBALS['phpgw_info']['server']['sessions_type'] == 'db') 4937 || ($this->use_private_table == True)) 4938 { 4939 // generic fallback value 4940 $my_location = (string)$acctnum.';'.$data_name; 4941 if (((string)$ex_folder != '') 4942 && ((string)$ex_msgnum != '') 4943 && ((string)$ex_part_no != '')) 4944 { 4945 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder.';'.$ex_msgnum.';'.$ex_part_no; 4946 } 4947 elseif (((string)$ex_folder != '') 4948 && ((string)$ex_msgnum != '')) 4949 { 4950 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder.';'.$ex_msgnum; 4951 } 4952 elseif ((string)$ex_folder != '') 4953 { 4954 $my_location = (string)$acctnum.';'.$data_name.';'.$ex_folder; 4955 } 4956 4957 if ($this->use_private_table == True) 4958 { 4959 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): we are using private table, SO we have this additional step to blank data in the "phpgw_anglemail" table, $my_location ['.$my_location.']<br />'); } 4960 $this->so->so_delete_data($my_location); 4961 } 4962 else 4963 { 4964 if ($this->debug_session_caching > 1) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): sessions_type is ['.$GLOBALS['phpgw_info']['server']['sessions_type'].'] SO we have this additional step to blank data in the "phpgw_app_sessions" table, $my_location ['.$my_location.']<br />'); } 4965 $GLOBALS['phpgw']->session->appsession($my_location, 'email', ''); 4966 } 4967 } 4968 4969 //if ((!$ex_folder) 4970 //&& (!$ex_msgnum) 4971 if (((string)$ex_folder == '') 4972 && ((string)$ex_msgnum == '') 4973 && (isset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name]))) 4974 { 4975 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name] = ''; 4976 unset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name]); 4977 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): LEAVING return True, did expire existing data for [email][dat]['.$acctnum.']['.$data_name.']<br />'); } 4978 return True; 4979 } 4980 //elseif (($ex_folder) 4981 //&& (!$ex_msgnum) 4982 elseif (((string)$ex_folder != '') 4983 && ((string)$ex_msgnum == '') 4984 && (isset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder]))) 4985 { 4986 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder] = ''; 4987 unset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder]); 4988 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): LEAVING return True, did expire existing data for [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']<br />'); } 4989 return True; 4990 } 4991 //elseif (($ex_folder) 4992 //&& ($ex_msgnum) 4993 elseif (((string)$ex_folder != '') 4994 && ((string)$ex_msgnum != '') 4995 && (isset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum]))) 4996 { 4997 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum] = ''; 4998 unset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum]); 4999 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): LEAVING return True, did expire existing data for [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.']<br />'); } 5000 return True; 5001 } 5002 elseif (((string)$ex_folder != '') 5003 && ((string)$ex_msgnum != '') 5004 && ((string)$ex_part_no != '') 5005 && (isset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no]))) 5006 { 5007 $this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no] = ''; 5008 unset($this->ref_SESSION['phpgw_session']['phpgw_app_sessions']['email']['dat'][$acctnum][$data_name][$ex_folder][$ex_msgnum][$ex_part_no]); 5009 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): LEAVING return True, did expire existing data for [email][dat]['.$acctnum.']['.$data_name.']['.$ex_folder.']['.$ex_msgnum.']['.$ex_part_no.']<br />'); } 5010 return True; 5011 } 5012 if ($this->debug_session_caching > 0) { $this->dbug->out('mail_msg: expire_session_cache_item('.__LINE__.'): LEAVING, return False, data did not exist for [email][dat]['.$acctnum.']['.$data_name.']['.serialize($ex_folder).']['.serialize($ex_msgnum).']['.serialize($ex_part_no).']<br />'); } 5013 return False; 5014 } 5015 5016 5017 /**************************************************************************\ 5018 * END CACHING HANDLERS * 5019 * - - - - - - - - - - - - - - - - - - - - - - - - - * 5020 * BEGIN PARAM / ARGS / PREFS ACCESS FUNCTIONS * 5021 \**************************************************************************/ 5022 5023 /*! 5024 @capability OOP-Style Access Methods to Private Object Properties 5025 @abstract simple access methods to read and set data, with transparent account number handling 5026 @discussion When multiple email accounts are enables, they may even be active at the same time, 5027 thus the properties and preferences for any individual email account must be distinctly accessable 5028 for each email account with as little brain damage to the developer as possible. These access methods 5029 server two purposes: 5030 (1) centralize access to all params and oprefs into a common, standardized methodology, and 5031 (2) these access functions also transparently handly the dirty work of tracking which email account 5032 the data applies to, takes care of any special handling a param may require, and it's classic OOP style. 5033 With the exception of a few paramaters/arguments that are not specific to any individual email acount, 5034 such as for private, internal object core properties, the developer need only use these functions to 5035 access object params, arguments, and preferences. 5036 @author Angles 5037 */ 5038 5039 /*! 5040 @function get_acctnum 5041 @abstract read which account number the object is currently activated on 5042 @param $unset_returns_default boolean default True. If no acctnum is currently set, 5043 should this function return a boolean False or a hardcoded "fallback default" account number, 5044 typically integer 0. Default is to return a fallback default account number. 5045 @returns (most typically) the internal account number of the currently active email account, 5046 but can be set, via the $unset_returns_default param, 5047 @discussion When multiple email accounts are enabled, all arg/param and preference access 5048 functions "pivot" off of this "object->acctnum" property, it serves essentially as the array key 5049 which maps the various access functions to the data of the intended account number. 5050 DEVELOPERS NOTE: The integer zero returned by this function can sometimes be mistaken 5051 as "empty" of "false", when using conditionals such as 5052 if ($my_acctnum) { then do this }; 5053 may incorrectly interper integer 0 as a "false" and this example conditional would not behave 5054 as expected, since there is infact a valid acount number of 0 in the variable. The preferred test 5055 for that type of condition is: 5056 if ((string)$my_acctnum != '') { then do this }; 5057 which produces a more desirable result. 5058 @author Angles 5059 */ 5060 function get_acctnum($unset_returns_default=True) 5061 { 5062 if ($this->debug_accts > 0) { $this->dbug->out('mail_msg: get_acctnum: ENTERING, (parm $unset_returns_default=['.serialize($unset_returns_default).'])<br />'); } 5063 5064 if ((isset($this->acctnum)) 5065 && ((string)$this->acctnum != '')) 5066 { 5067 if ($this->debug_accts > 0) { $this->dbug->out('mail_msg: get_acctnum: LEAVING, $this->acctnum exists, returning it: '.serialize($this->acctnum).'<br />'); } 5068 return $this->acctnum; 5069 } 5070 // ok, no useful acctnumber exists, what should we do 5071 elseif ($unset_returns_default == True) 5072 { 5073 5074 if ($this->debug_accts > 0) { $this->dbug->out('mail_msg: get_acctnum: LEAVING, NO $this->acctnum exists, returning $this->fallback_default_acctnum : '.serialize($this->fallback_default_acctnum).'<br />'); } 5075 return $this->fallback_default_acctnum; 5076 } 5077 else 5078 { 5079 if ($this->debug_accts > 0) { $this->dbug->out('mail_msg: get_acctnum: LEAVING, NO $this->acctnum exists, returning FALSE<br />'); } 5080 return False; 5081 } 5082 } 5083 5084 /*! 5085 @function set_acctnum 5086 @abstract instruct the object which email account is the desired active account for all params, 5087 args, and preferences should refer to. 5088 @param $acctnum integer 5089 @result True if a valid param $acctnum is given and the object->acctnum value is set, False if 5090 invalid data is passed in the param. 5091 @author Angles 5092 @discussion ? 5093 @access public 5094 */ 5095 function set_acctnum($acctnum='') 5096 { 5097 if ($this->debug_accts > 0) { $this->dbug->out('mail_msg: set_acctnum: ENTERING, (parm $acctnum=['.serialize($acctnum).'])<br />'); } 5098 if ((isset($acctnum)) 5099 && ((string)$acctnum != '')) 5100 { 5101 $this->acctnum = $acctnum; 5102 if ($this->debug_accts > 0) { $this->dbug->out('mail_msg: set_acctnum: LEAVING, returning True, made $this->acctnum = $acctnum ('.serialize($acctnum).')<br />'); } 5103 return True; 5104 } 5105 else 5106 { 5107 if ($this->debug_accts > 0) { $this->dbug->out('mail_msg: set_acctnum: LEAVING, returning False, value $acctnum not sufficient to set $this->acctnum<br />'); } 5108 return False; 5109 } 5110 } 5111 5112 5113 /* * * * * * * * * * * * * * * * * * 5114 * OOP-Style Access Methods for Preference Values 5115 * * * * * * * * * * * * * * * * * */ 5116 /*! 5117 @function get_pref_value 5118 @abstract OOP access of pref items for any given email account. 5119 @param $pref_name (string) id if the desired pref item 5120 @param $acctnum (int) OPTIONAL acctnum this applies to, "current acctnum" will be supplied if this arg is not given. 5121 @result value of the desired pref IF it exists, if no you are returned nothing (null). 5122 @discussion ? 5123 @access public 5124 @author Angles 5125 */ 5126 function get_pref_value($pref_name='',$acctnum='') 5127 { 5128 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_pref_value: ENTERING, $pref_name: ['.$pref_name.'] $acctnum: ['.$acctnum.']'.'<br />'); } 5129 if ((!isset($acctnum)) 5130 || ((string)$acctnum == '')) 5131 { 5132 $acctnum = $this->get_acctnum(); 5133 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers): get_pref_value: obtained acctnum from "$this->get_acctnum()", got $acctnum: ['.$acctnum.']'.'<br />'); } 5134 } 5135 5136 if ((isset($pref_name)) 5137 && ((string)$pref_name != '') 5138 && (isset($this->a[$acctnum]['prefs'][$pref_name]))) 5139 { 5140 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_pref_value: LEAVING, returning $this->a['.$acctnum.'][prefs]['.$pref_name.'] : ['.$this->a[$acctnum]['prefs'][$pref_name].'] <br />'); } 5141 return $this->a[$acctnum]['prefs'][$pref_name]; 5142 } 5143 else 5144 { 5145 // arg not set, or invalid input $arg_name 5146 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_pref_value: LEAVING with ERRROR, pref item was not found<br />'); } 5147 return; 5148 } 5149 } 5150 5151 /*! 5152 @function set_pref_value 5153 @abstract set pref value for a pref items for any given email account, TEMPORARY to this page view. 5154 @param $pref_name (string) 5155 @param $this_value (string, int, or array) 5156 @param $acctnum (int) OPTIONAL 5157 @result True if pref value was set, False on failure to set the item, such as invalid data is passed in the param. 5158 @author Angles 5159 @discussion Used when certain prefs are derived from other prefs, they may not actually exist in the 5160 prefs DB, so we figure them out in the code somewhere and set the value here, Lasts only as long a 5161 a single script run. 5162 @access public 5163 */ 5164 function set_pref_value($pref_name='', $this_value='', $acctnum='') 5165 { 5166 if ((!isset($acctnum)) 5167 || ((string)$acctnum == '')) 5168 { 5169 $acctnum = $this->get_acctnum(); 5170 } 5171 5172 if ((isset($pref_name)) 5173 && ((string)$pref_name != '')) 5174 { 5175 $this->a[$acctnum]['prefs'][$pref_name] = $this_value; 5176 // return True to indicate success 5177 return True; 5178 } 5179 else 5180 { 5181 // return False to indicate invalid input $arg_name 5182 return False; 5183 } 5184 } 5185 5186 /*! 5187 @function get_isset_pref 5188 @abstract Check if a given preference is set 5189 @param $pref_name (string) 5190 @param $acctnum (int) OPTIONAL 5191 @result True if preference $pref_name value exists, False if not 5192 @author Angles 5193 @discussion It is common the boolean preference items are simply not set if their value 5194 is supposed to be false. This function can be used for this discovery. Note that some 5195 string preferences items, such as the email sig, can be set yet have a value of an empty string, 5196 in this case this function follows strict logic and returns True because the preference exists. 5197 Similarly, uwash mail location is another example of a preference item where an empty string 5198 is a valid value. 5199 @access public 5200 */ 5201 function get_isset_pref($pref_name='',$acctnum='') 5202 { 5203 if ((!isset($acctnum)) 5204 || ((string)$acctnum == '')) 5205 { 5206 $acctnum = $this->get_acctnum(); 5207 } 5208 // error check 5209 if ((isset($pref_name)) 5210 && ((string)$pref_name != '') 5211 && (isset($this->a[$acctnum]['prefs'][$pref_name]))) 5212 { 5213 return True; 5214 } 5215 else 5216 { 5217 // arg not set, or invalid input $arg_name 5218 return False; 5219 } 5220 } 5221 5222 /*! 5223 @function unset_pref 5224 @abstract unset a preference item. 5225 @param $pref_name (string) 5226 @param $acctnum (int) OPTIONAL 5227 @result True if $pref_name existed and was made unset, False on failure, such as $pref_name not 5228 being set in the first place. This function can not unset something that does not exist to begin with. 5229 @author Angles 5230 @discussion ? 5231 @access public 5232 */ 5233 function unset_pref($pref_name='', $acctnum='') 5234 { 5235 if ((!isset($acctnum)) 5236 || ((string)$acctnum == '')) 5237 { 5238 $acctnum = $this->get_acctnum(); 5239 } 5240 5241 if ((isset($pref_name)) 5242 && ((string)$pref_name != '')) 5243 { 5244 $this->a[$acctnum]['prefs'][$pref_name] = ''; 5245 unset($this->a[$acctnum]['prefs'][$pref_name]); 5246 // return True to indicate success 5247 return True; 5248 } 5249 else 5250 { 5251 // return False to indicate invalid input $pref_name 5252 return False; 5253 } 5254 } 5255 5256 /*! 5257 @function get_all_prefs 5258 @abstract get the entire preference data array FOR ONE ACCOUNT 5259 @param $acctnum (int) OPTIONAL 5260 @result none 5261 @author Angles 5262 @discussion The result are not the raw preferences directly from the database, this function returns 5263 the preference array for an email account as explosed to the email app, that is these are preferences that 5264 have passed through some logic to process and normalize them, 5265 @access public 5266 */ 5267 function get_all_prefs($acctnum='') 5268 { 5269 if ((!isset($acctnum)) 5270 || ((string)$acctnum == '')) 5271 { 5272 $acctnum = $this->get_acctnum(); 5273 } 5274 5275 if (isset($this->a[$acctnum]['prefs'])) 5276 { 5277 return $this->a[$acctnum]['prefs']; 5278 } 5279 else 5280 { 5281 // arg not set, or invalid input $arg_name 5282 return; 5283 } 5284 } 5285 5286 /*! 5287 @function set_pref_array 5288 @abstract set the entire preference data array FOR ONE ACCOUNT 5289 @param $pref_array_data (array) either (a) correctly formed email pref array data, or (b) an empty array 5290 @param $acctnum (int) OPTIONAL 5291 @result boolean True is successfully sets $pref_array_data, False to indicate all we did was clear the args, no data was fed 5292 @author Angles 5293 @discussion NOTE the first thing this function does is clear the existing preference array for the 5294 emal account. This happens no matter what. This effectively is a way to clear an accounts email preference 5295 array by passing an empty array, which can be useful in certain situations. More commonly this function 5296 is used to set the entire preference array for an account in one operation. In that case you better know 5297 what youre doing, $pref_array_data must be correctly formed emai pref array data. By clearing the 5298 existing preference array no matter what, this is why a return value of False indicates that, while no 5299 new preference data was set, still something did occur and that was the clearing of any pre-existing 5300 preference array. 5301 @access private 5302 */ 5303 function set_pref_array($pref_array_data='', $acctnum='') 5304 { 5305 if ((!isset($acctnum)) 5306 || ((string)$acctnum == '')) 5307 { 5308 $acctnum = $this->get_acctnum(); 5309 } 5310 5311 $this->a[$acctnum]['prefs'] = array(); 5312 5313 if ((isset($pref_array_data)) 5314 && (count($pref_array_data > 0))) 5315 { 5316 $this->a[$acctnum]['prefs'] = $pref_array_data; 5317 // return True to indicate we filled, not just cleared 5318 return True; 5319 } 5320 else 5321 { 5322 // return False to indicate all we did was clear the args, no data was fed 5323 return False; 5324 } 5325 } 5326 5327 5328 /* * * * * * * * * * * * * * * * * * 5329 * OOP-Style Access Methods for Class Params/Args Values 5330 * * * * * * * * * * * * * * * * * */ 5331 /*! 5332 @function _get_arg_is_known 5333 @abstract utility function for private use, tests if a given $arg_name is in the $this->known_external_args[] array. 5334 @param $arg_name (string) 5335 @param $calling_function_name (string) used for debug output 5336 @result boolean 5337 @author Angles 5338 @discussion ? 5339 @access private 5340 */ 5341 function _get_arg_is_known($arg_name='', $calling_function_name='') 5342 { 5343 // skip this unless debug level 4 5344 if ($this->debug_args_oop_access < 4) 5345 { 5346 return False; 5347 } 5348 5349 if ($arg_name == '') 5350 { 5351 return False; 5352 } 5353 if ($calling_function_name == '') 5354 { 5355 $calling_function_name == 'UNSPECIFIED'; 5356 } 5357 // loop thru known externally controlled args 5358 $finding = False; 5359 $report = ''; 5360 for($i=0; $i < count($this->known_external_args); $i++) 5361 { 5362 if ($arg_name == $this->known_external_args[$i]) 5363 { 5364 $finding = True; 5365 $report = '*is* known (external)'; 5366 break; 5367 } 5368 } 5369 // check internal args 5370 for($i=0; $i < count($this->known_internal_args); $i++) 5371 { 5372 if ($arg_name == $this->known_internal_args[$i]) 5373 { 5374 $finding = True; 5375 $report = '*is* known (internal)'; 5376 break; 5377 } 5378 } 5379 if (!$finding) 5380 { 5381 $report = '*NOT* KNOWN *NOT* KNOWN *NOT* KNOWN *NOT* KNOWN'; 5382 } 5383 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): _arg_is_known: TEST: '.$report.' ; $arg_name: ['.$arg_name.'] called by $calling_function_name: ['.$calling_function_name.'] '.'<br />'); } 5384 return $finding; 5385 } 5386 5387 /*! 5388 @function get_isset_arg 5389 @abstract Check if a given variable is set 5390 @param $arg_name (string) 5391 @param $acctnum (int) OPTIONAL 5392 @param $extra_keys (string) for SPECIAL INTERNAL use only. Rarely used. DEPRECIATED use sublevels instead. 5393 @result boolean 5394 @author Angles 5395 @discussion ? 5396 @access public 5397 */ 5398 function get_isset_arg($arg_name='',$acctnum='', $extra_keys='') 5399 { 5400 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_isset_arg: ENTERING, $arg_name: ['.$arg_name.'] $acctnum: ['.$acctnum.']'.'<br />'); } 5401 if ($this->debug_args_oop_access > 1) { $this->_get_arg_is_known($arg_name, 'get_isset_arg'); } 5402 5403 if ((!isset($acctnum)) 5404 || ((string)$acctnum == '')) 5405 { 5406 $acctnum = $this->get_acctnum(); 5407 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers): get_isset_arg: obtained $acctnum from $this->get_acctnum(): ['.$acctnum.']'.'<br />'); } 5408 } 5409 5410 /* 5411 // OOP VERSION if PROBLEMATIC 5412 // but it may not give intended answer because 5413 // "get_arg_value" will handoff processing to specialized functions that WILL fill the value 5414 // sometimes simply with default values, which would cause this function to return unexpected results 5415 $test_this = $this->get_arg_value($arg_name, $acctnum); 5416 if (isset($test_this)) 5417 { 5418 return True; 5419 } 5420 */ 5421 5422 // Best Version at this time, if something is not set, DO NOT handoff to a support function to fill it 5423 // that way we can return false if something is indeed NOT set 5424 5425 // $arg_name has sub-levels 5426 if ((isset($arg_name)) 5427 && ((string)$arg_name != '') 5428 && (strstr($arg_name, ']['))) 5429 { 5430 // request for $arg_name['sub-element'] 5431 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers): get_isset_arg: $arg_name is requesting sub-level array element(s), use EVAL, $arg_name: '.serialize($arg_name).'<br />'); } 5432 $evaled = ''; 5433 //$code = '$evaled = $this->a[$acctnum][\'args\']'.$arg_name.';'; 5434 $code = '$evaled = $this->a[$acctnum]["args"]'.$arg_name.';'; 5435 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' * $code: '.$code.'<br />'); } 5436 eval($code); 5437 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' * $evaled: '.$evaled.'<br />'); } 5438 if (isset($evaled)) 5439 { 5440 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_isset_arg: LEAVING returning $evaled: ['.$evaled.'] produced by $code: '.$code.'<br />'); } 5441 return True; 5442 } 5443 } 5444 // $arg_name has NO sub-levels 5445 elseif ((isset($this->a[$acctnum]['args'][$arg_name])) 5446 && (!$extra_keys)) 5447 { 5448 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_isset_arg: LEAVING returning $this->a[$acctnum('.$acctnum.')][args][$arg_name]: '.$this->a[$acctnum]['args'][$arg_name].'<br />'); } 5449 return True; 5450 } 5451 elseif ((isset($this->a[$acctnum]['args'][$arg_name][$extra_keys])) 5452 && ($extra_keys)) 5453 { 5454 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_isset_arg: LEAVING (using EXTRA_KEYS) returning $this->a[$acctnum('.$acctnum.')][args][$arg_name][$extra_keys]: '.$this->a[$acctnum]['args'][$arg_name][$extra_keys].'<br />'); } 5455 return True; 5456 } 5457 // if we get here, it was not set 5458 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_isset_arg: LEAVING returning False<br />'); } 5459 return False; 5460 } 5461 5462 /*! 5463 @function unset_arg 5464 @abstract unset a class variable 5465 @param $arg_name (string) 5466 @param $acctnum (int) OPTIONAL 5467 @result boolean True if $arg_name existed and was made unset, False on failure, such as $arg_name not 5468 being set in the first place. This function can not unset something that does not exist to begin with. 5469 @author Angles 5470 @discussion ? 5471 @access public 5472 */ 5473 function unset_arg($arg_name='', $acctnum='') 5474 { 5475 if ($this->debug_args_oop_access > 1) { $this->_get_arg_is_known($arg_name, 'unset_arg'); } 5476 5477 if ((!isset($acctnum)) 5478 || ((string)$acctnum == '')) 5479 { 5480 $acctnum = $this->get_acctnum(); 5481 } 5482 5483 // $arg_name has sub-levels 5484 if ((isset($arg_name)) 5485 && ((string)$arg_name != '') 5486 && (strstr($arg_name, ']['))) 5487 { 5488 // make it equal a blank string 5489 $code = '$this->a[$acctnum]["args"]'.$arg_name.' = "";'; 5490 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): unset_arg (sublevels): $arg_name is requesting sub-level array element(s), use EVAL, $arg_name: '.serialize($arg_name).'<br />'); } 5491 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' unset_arg (sublevels) * $code: '.$code.'<br />'); } 5492 eval($code); 5493 // unset it 5494 $code = 'unset($this->a[$acctnum]["args"]'.$arg_name.');'; 5495 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): unset_arg (sublevels): $arg_name is requesting sub-level array element(s), use EVAL, $arg_name: '.serialize($arg_name).'<br />'); } 5496 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' unset_arg (sublevels) * $code: '.$code.'<br />'); } 5497 eval($code); 5498 5499 // now were we successful? 5500 $code = '$evaled = isset($this->a[$acctnum]["args"]'.$arg_name.');'; 5501 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): unset_arg (sublevels): VERIFY that we succeeded, again use EVAL, $arg_name: '.serialize($arg_name).'<br />'); } 5502 $evaled = ''; 5503 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' unset_arg(sublevels): (VERIFY) * $code: '.$code.'<br />'); } 5504 eval($code); 5505 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' unset_arg(sublevels): (VERIFY) * $evaled: '.$evaled.'<br />'); } 5506 if (isset($evaled)) 5507 { 5508 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): unset_arg (sublevels): LEAVING returning False, FAILED to unset arg, because VERIFY showed $evaled is still set<br />'); } 5509 return False; 5510 } 5511 else 5512 { 5513 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): unset_arg (sublevels): LEAVING returning True, because VERIFY showed $evaled is unset<br />'); } 5514 return True; 5515 } 5516 } 5517 elseif ((isset($arg_name)) 5518 && ((string)$arg_name != '')) 5519 { 5520 $this->a[$acctnum]['args'][$arg_name] = ''; 5521 unset($this->a[$acctnum]['args'][$arg_name]); 5522 // return True to indicate success 5523 return True; 5524 } 5525 else 5526 { 5527 // return False to indicate invalid input $arg_name 5528 return False; 5529 } 5530 } 5531 5532 /*! 5533 @function get_arg_value 5534 @abstract Obtain the value of a given class variable, will handoff to helper functions if necessary. 5535 @param $arg_name (string) 5536 @param $acctnum (int) OPTIONAL 5537 @param $extra_keys (string) for SPECIAL INTERNAL use only. Rarely used. If arg uses a "special handler", that handler BETTER support this too, if used. 5538 Currently no arg that requires a "special handler" uses an $extra_keys param anyway. DEPRECIATED use sublevels instead. 5539 @result (string, int, or array) 5540 @author Angles 5541 @discussion Some class variables, such as "mailsvr_namespace", have functions dedicated only to determining their value. 5542 In these cases this function will hand off the request directly to that specialized function. In other cases the 5543 class variable desired is a simple variable and its value is returned. 5544 @access public 5545 */ 5546 function get_arg_value($arg_name='',$acctnum='', $extra_keys='') 5547 { 5548 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: ENTERING ($arg_name: ['.$arg_name.'], $acctnum: ['.$acctnum.'] )<br />'); } 5549 if ($this->debug_args_oop_access > 1) { $this->_get_arg_is_known($arg_name, 'get_arg_value'); } 5550 5551 if ((!isset($acctnum)) 5552 || ((string)$acctnum == '')) 5553 { 5554 $acctnum = $this->get_acctnum(); 5555 } 5556 5557 if ((isset($arg_name)) 5558 && ((string)$arg_name != '')) 5559 { 5560 // ---- SPECIAL HANDLERS ---- 5561 if ($arg_name == 'mailsvr_callstr') 5562 { 5563 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING with HANDOFF to get_mailsvr_callstr('.$acctnum.')<br />'); } 5564 return $this->get_mailsvr_callstr($acctnum); 5565 } 5566 elseif ($arg_name == 'mailsvr_namespace') 5567 { 5568 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING with HANDOFF to get_mailsvr_namespace('.$acctnum.')<br />'); } 5569 return $this->get_mailsvr_namespace($acctnum); 5570 } 5571 elseif ($arg_name == 'mailsvr_delimiter') 5572 { 5573 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING with HANDOFF to get_mailsvr_delimiter('.$acctnum.')<br />'); } 5574 return $this->get_mailsvr_delimiter($acctnum); 5575 } 5576 elseif ($arg_name == 'folder_list') 5577 { 5578 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING with HANDOFF to get_folder_list()<br />'); } 5579 return $this->get_folder_list($acctnum); 5580 } 5581 elseif ($arg_name == 'verified_trash_folder_long') 5582 { 5583 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING with HANDOFF to get_verified_trash_folder_long()<br />'); } 5584 return $this->get_verified_trash_folder_long($acctnum); 5585 } 5586 /* 5587 elseif ($arg_name == 'folder') 5588 { 5589 if ($this->debug_args_oop_access > 1) { echo 'mail_msg(_wrappers): get_arg_value: request for backwards compat arg "folder"<br />'; } 5590 // look for foder in (1) msgball , then (2) fldball , then (3) return default value INBOX 5591 if ( (isset($this->a[$acctnum]['args']['msgball']['folder'])) 5592 && ($this->a[$acctnum]['args']['msgball']['folder'] != '') ) 5593 { 5594 $folder_arg_decision = $this->a[$acctnum]['args']['msgball']['folder']; 5595 if ($this->debug_args_oop_access > 1) { echo 'mail_msg(_wrappers): get_arg_value: request for "folder" will use value in $this->a['.$acctnum.'][args][msgball][folder] = ['.$folder_arg_decision.']<br />'; } 5596 } 5597 elseif ( (isset($this->a[$acctnum]['args']['fldball']['folder'])) 5598 && ($this->a[$acctnum]['args']['fldball']['folder'] != '') ) 5599 { 5600 $folder_arg_decision = $this->a[$acctnum]['args']['fldball']['folder']; 5601 if ($this->debug_args_oop_access > 1) { echo 'mail_msg(_wrappers): get_arg_value: request for "folder" will use value in $this->a['.$acctnum.'][args][fldball][folder] = ['.$folder_arg_decision.']<br />'; } 5602 } 5603 else 5604 { 5605 if ($this->debug_args_oop_access > 1) { echo 'mail_msg(_wrappers): get_arg_value: request for "folder" using "INBOX", found nothing in [args][msgball][folder] nor [args][fldball][folder]<br />'; } 5606 $folder_arg_decision = 'INBOX'; 5607 } 5608 if ($this->debug_args_oop_access > 0) { echo 'mail_msg(_wrappers): get_arg_value: LEAVING, returning (backward compat) $folder_arg_decision ['.$folder_arg_decision.']<br />'; } 5609 return $folder_arg_decision; 5610 } 5611 */ 5612 // ---- STANDARD HANDLER (arg_name has sub-levels) ---- 5613 elseif (strstr($arg_name, '][')) 5614 { 5615 if ($extra_keys) 5616 { 5617 // request for $arg_name['sub-element'] [$extra_keys] 5618 // represents code which typically is an array referencing a system/api property 5619 $code = '$evaled = $this->a[$acctnum]["args"]'.$arg_name.'[$extra_keys];'; 5620 } 5621 else 5622 { 5623 // request for $arg_name['sub-element'] 5624 // represents code which typically is an array referencing a system/api property 5625 //$code = '$evaled = $this->a[$acctnum][\'args\']'.$arg_name.';'; 5626 $code = '$evaled = $this->a[$acctnum]["args"]'.$arg_name.';'; 5627 } 5628 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: $arg_name is requesting sub-level array element(s), use EVAL, $arg_name: '.serialize($arg_name).'<br />'); } 5629 $evaled = ''; 5630 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' * $code: '.$code.'<br />'); } 5631 eval($code); 5632 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' * $evaled: '.$evaled.'<br />'); } 5633 if ((isset($evaled)) 5634 && (!$extra_keys) 5635 && (strstr($arg_name, 'folder_status_info'))) 5636 { 5637 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: sublevels with folder_status_info NEED values to be serialized since we eval it, so unserialize(base64_decode($evaled)) now: <br />'); } 5638 $evaled = unserialize(base64_decode($evaled)); 5639 } 5640 if (isset($evaled)) 5641 { 5642 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING returning $evaled: ['.$evaled.'] produced by $code: '.$code.'<br />'); } 5643 return $evaled; 5644 } 5645 } 5646 // ---- STANDARD HANDLER (arg_name has NO sub-levels) ---- 5647 elseif (($extra_keys) 5648 && (isset($this->a[$acctnum]['args'][$arg_name][$extra_keys]))) 5649 { 5650 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING returning $this->a[$acctnum('.$acctnum.')][args][$arg_name]: '.$this->a[$acctnum]['args'][$arg_name].'<br />'); } 5651 return $this->a[$acctnum]['args'][$arg_name]; 5652 } 5653 elseif ((!$extra_keys) 5654 && (isset($this->a[$acctnum]['args'][$arg_name]))) 5655 { 5656 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING returning $this->a[$acctnum('.$acctnum.')][args][$arg_name]: '.$this->a[$acctnum]['args'][$arg_name].'<br />'); } 5657 return $this->a[$acctnum]['args'][$arg_name]; 5658 } 5659 } 5660 5661 // we ONLY get here if there's no data to return, 5662 // arg not set, or invalid input $arg_name 5663 // otherwise, anything that is sucessful returns and exist at that point, never gets to here 5664 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value: LEAVING, returning *nothing*, arg not set of input arg invalid, using naked "return" call<br />'); } 5665 return; 5666 } 5667 5668 /*! 5669 @function _direct_access_arg_value 5670 @abstract utility function for private use, used to bypass any special handlers, to directly access the "args" array. 5671 @param $arg_name (string) 5672 @param $acctnum (int) optional 5673 @result (mixed) 5674 @author Angles 5675 @discussion Esoteric utility function for specialized private use. 5676 @access private 5677 */ 5678 function _direct_access_arg_value($arg_name='',$acctnum='') 5679 { 5680 if ($this->debug_args_oop_access > 1) { $this->_get_arg_is_known($arg_name, '_direct_access_arg_value'); } 5681 5682 // PRIVATE - for use by internal functions 5683 if ((!isset($acctnum)) 5684 || ((string)$acctnum == '')) 5685 { 5686 $acctnum = $this->get_acctnum(); 5687 } 5688 // $this->set_arg_value('["folder_status_info"]["'.$ex_folder.'"]', $empty_array, $acctnum); 5689 5690 if (isset($this->a[$acctnum]['args'][$arg_name])) 5691 { 5692 return $this->a[$acctnum]['args'][$arg_name]; 5693 } 5694 else 5695 { 5696 // arg not set, or invalid input $arg_name 5697 return; 5698 } 5699 } 5700 5701 /*! 5702 @function _get_arg_ref 5703 @abstract utility function for private use, used to bypass any special handlers, get a reference to something in 5704 the args array. 5705 @param $arg_name (string) 5706 @param $acctnum (int) optional 5707 @result (mixed) direct refernce to an arg value in memory, or a reference to a constant "##NOTHING##" on failure. 5708 @author Angles 5709 @discussion Esoteric utility function for specialized private use. Primary for use where speed is an issue. 5710 NOTE: Returning References requires the ampersand in BOTH the call to the function AND the function 5711 declaration here. 5712 @example 5713 function &find_var ($param) 5714 { 5715 ...code... 5716 return $found_var; 5717 } 5718 $foo =& find_var ($bar); 5719 // that was straing from the phpmanual 5720 @access private 5721 */ 5722 function &_get_arg_ref($arg_name='',$acctnum='') 5723 { 5724 if ($this->debug_args_oop_access > 1) { $this->_get_arg_is_known($arg_name, 'get_arg_ref'); } 5725 5726 // PRIVATE - for use by internal functions 5727 if ((!isset($acctnum)) 5728 || ((string)$acctnum == '')) 5729 { 5730 $acctnum = $this->get_acctnum(); 5731 } 5732 5733 if (isset($this->a[$acctnum]['args'][$arg_name])) 5734 { 5735 return $this->a[$acctnum]['args'][$arg_name]; 5736 } 5737 else 5738 { 5739 // arg not set, or invalid input $arg_name 5740 //return '##NOTHING##'; 5741 return $this->nothing; 5742 } 5743 } 5744 5745 5746 /*! 5747 @function get_arg_value_ref 5748 @abstract return reference to the value, but smart enough to make it if possible, then return reference. 5749 @param (string) $arg_name 5750 @param (int) $acctnum (optional) 5751 @result REFERENCE 5752 @discussion get a ref instead of a copy of a value, Try to use "special handler" to generate the 5753 value if it does not already exist, then again try to return the reference. Returns ref to 5754 $this->nothing on failure. 5755 @author Angles 5756 */ 5757 function &get_arg_value_ref($arg_name='',$acctnum='') 5758 { 5759 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: ENTERING ($arg_name: ['.$arg_name.'], $acctnum: ['.$acctnum.'] )<br />'); } 5760 if ($this->debug_args_oop_access > 1) { $this->_get_arg_is_known($arg_name, 'get_arg_value_ref'); } 5761 5762 if ((!isset($acctnum)) 5763 || ((string)$acctnum == '')) 5764 { 5765 $acctnum = $this->get_acctnum(); 5766 } 5767 5768 if (isset($this->a[$acctnum]['args'][$arg_name])) 5769 { 5770 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: LEAVING found and returning ref for ['.$arg_name.'] for ['.$acctnum.']<br />'); } 5771 return $this->a[$acctnum]['args'][$arg_name]; 5772 } 5773 else 5774 { 5775 // try to geberate the arg value, then again try to return the ref 5776 if ($arg_name == 'mailsvr_callstr') 5777 { 5778 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: generate arg value using get_mailsvr_callstr('.$acctnum.')<br />'); } 5779 $this->get_mailsvr_callstr($acctnum); 5780 5781 } 5782 elseif ($arg_name == 'mailsvr_namespace') 5783 { 5784 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: generate arg value using get_mailsvr_namespace('.$acctnum.')<br />'); } 5785 $this->get_mailsvr_namespace($acctnum); 5786 } 5787 elseif ($arg_name == 'mailsvr_delimiter') 5788 { 5789 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: generate arg value using get_mailsvr_delimiter('.$acctnum.')<br />'); } 5790 $this->get_mailsvr_delimiter($acctnum); 5791 } 5792 elseif ($arg_name == 'folder_list') 5793 { 5794 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: generate arg value using get_folder_list()<br />'); } 5795 $this->get_folder_list($acctnum); 5796 } 5797 elseif ($arg_name == 'verified_trash_folder_long') 5798 { 5799 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: generate arg value using get_verified_trash_folder_long()<br />'); } 5800 $this->get_verified_trash_folder_long($acctnum); 5801 } 5802 else 5803 { 5804 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: could not find "special handler" to generate an arg value, returning ref to $this->nothing ['.$this->nothing.']<br />'); } 5805 return $this->nothing; 5806 } 5807 } 5808 // ok, we tried to generate the arg value, were we successful? 5809 if (isset($this->a[$acctnum]['args'][$arg_name])) 5810 { 5811 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: LEAVING was able to generate arg value, found and returning ref for ['.$arg_name.'] for ['.$acctnum.']<br />'); } 5812 return $this->a[$acctnum]['args'][$arg_name]; 5813 } 5814 // fallback, we must have failed to find or make then find an arg value, so no reference to something we can not find 5815 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers): get_arg_value_ref: if we get here we probably tried but failed to generate a arg value (tried a "special handler"), so returning ref to $this->nothing ['.$this->nothing.']<br />'); } 5816 return $this->nothing; 5817 } 5818 5819 /*! 5820 @function set_arg_value 5821 @abstract Sets a variable in the "args" array. Should only be used for args that do not require specialized functions. 5822 @param $arg_name (string) 5823 @param $this_value (mixed) 5824 @param $acctnum (int) optional 5825 @result (mixed) 5826 @author Angles 5827 @discussion ? 5828 @access public 5829 */ 5830 function set_arg_value($arg_name='', $this_value='', $acctnum='', $extra_keys='') 5831 { 5832 if ($this->debug_args_oop_access > 1) { $this->_get_arg_is_known($arg_name, 'set_arg_value'); } 5833 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): set_arg_value: ENTERING, $arg_name: ['.$arg_name.'] ; $this_value: ['.$this_value.'] ; $acctnum: ['.$acctnum.']<br />'); } 5834 5835 if ((!isset($acctnum)) 5836 || ((string)$acctnum == '')) 5837 { 5838 $acctnum = $this->get_acctnum(); 5839 } 5840 5841 // NOTE we have NO special handlers in this set code 5842 // ---- STANDARD HANDLER (arg_name has sub-levels) ---- 5843 if ((isset($arg_name)) 5844 && ((string)$arg_name != '') 5845 && (strstr($arg_name, ']['))) 5846 { 5847 // NOTE $this_value BETTER BE SIMPLE string or int if you are doing it like this 5848 if (strstr($arg_name, 'folder_status_info')) 5849 { 5850 $code = '$this->a[$acctnum]["args"]'.$arg_name.' = "'.base64_encode(serialize($this_value)).'";'; 5851 } 5852 elseif (is_string($this_value)) 5853 { 5854 $code = '$this->a[$acctnum]["args"]'.$arg_name.' = "'.$this_value.'";'; 5855 } 5856 else 5857 { 5858 $code = '$this->a[$acctnum]["args"]'.$arg_name.' = '.$this_value.';'; 5859 } 5860 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): set_arg_value (sublevels): $arg_name is requesting sub-level array element(s), use EVAL, $arg_name: '.serialize($arg_name).'<br />'); } 5861 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' set_arg_value (sublevels) * $code: '.$code.'<br />'); } 5862 eval($code); 5863 // additional handling to get an array into an evaled string 5864 //if (is_array($this_value)) 5865 //{ 5866 // $code = '$this->a[$acctnum]["args"]'.$arg_name.' = unserialize($this->a[$acctnum]["args"]'.$arg_name.');'; 5867 // if ($this->debug_args_oop_access > 1) { echo ' additional array handling: set_arg_value (sublevels) * $code: '.$code.'<br />'; } 5868 // eval($code); 5869 //} 5870 5871 // now were we successful? 5872 $code = '$evaled = $this->a[$acctnum]["args"]'.$arg_name.';'; 5873 if ($this->debug_args_oop_access > 1) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): set_arg_value (sublevels): VERIFY that we succeeded, again use EVAL, $arg_name: '.serialize($arg_name).'<br />'); } 5874 $evaled = ''; 5875 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' set_arg_value(sublevels): (VERIFY) * $code: '.$code.'<br />'); } 5876 eval($code); 5877 if ($this->debug_args_oop_access > 1) { $this->dbug->out(' set_arg_value(sublevels): (VERIFY) * $evaled (seriialized for this display): '.serialize($evaled).'<br />'); } 5878 if (isset($evaled)) 5879 { 5880 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): set_arg_value (sublevels): LEAVING returning True, VERIFY indicates $evaled was indeded set<br />'); } 5881 return True; 5882 } 5883 else 5884 { 5885 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): set_arg_value (sublevels): LEAVING returning False, FAILED to set arg value, because VERIFY showed $evaled was unset<br />'); } 5886 return False; 5887 } 5888 } 5889 // ---- STANDARD HANDLER (arg_name has NO sub-levels) ---- 5890 elseif ((isset($arg_name)) 5891 && ((string)$arg_name != '')) 5892 { 5893 /* 5894 // can not do prep_folder_in because it calls "folder_lookup" which requires an active mailsvr stream login 5895 // ---- SPECIAL HANDLERS ---- 5896 //if ($arg_name == 'folder') 5897 //{ 5898 // $processed_value = $this->prep_folder_in($this_value); 5899 // $this_value = $processed_value; 5900 //} 5901 */ 5902 // SET it, any special processing should be taken care just above here 5903 $this->a[$acctnum]['args'][$arg_name] = $this_value; 5904 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): set_arg_value: LEAVING, returning TRUE, set data $this->a['.$acctnum.'][args]['.$arg_name.']: ['.$this->a[$acctnum]['args'][$arg_name].']<br />'); } 5905 // return True to indicate success 5906 return True; 5907 } 5908 else 5909 { 5910 // return False to indicate invalid input $arg_name 5911 if ($this->debug_args_oop_access > 0) { $this->dbug->out('mail_msg(_wrappers)('.__LINE__.'): set_arg_value: LEAVING, returning FALSE, invalid $arg_name: ['.$arg_name.']<br />'); } 5912 return False; 5913 } 5914 } 5915 5916 /*! 5917 @function set_arg_array 5918 @abstract ? 5919 @param $arg_array_data (array) 5920 @param $acctnum (int) optional 5921 @result boolean 5922 @author Angles 5923 @discussion ? 5924 @access private 5925 */ 5926 function set_arg_array($arg_array_data='', $acctnum='') 5927 { 5928 if ((!isset($acctnum)) 5929 || ((string)$acctnum == '')) 5930 { 5931 $acctnum = $this->get_acctnum(); 5932 } 5933 5934 $this->a[$acctnum]['args'] = array(); 5935 5936 if ((isset($arg_array_data)) 5937 && (count($arg_array_data > 0))) 5938 { 5939 /* 5940 while(list($key,$value) = each($arg_array_data)) 5941 { 5942 $this->set_arg_value($key, $arg_array_data[$key]); 5943 } 5944 */ 5945 $this->a[$acctnum]['args'] = $arg_array_data; 5946 // return True to indicate we filled, not just cleared 5947 return True; 5948 } 5949 else 5950 { 5951 // return False to indicate all we did was clear the args, no data was fed 5952 return False; 5953 } 5954 } 5955 5956 /*! 5957 @function get_all_args 5958 @abstract ? 5959 @param $acctnum (int) optional 5960 @result (mixed) 5961 @author Angles 5962 @discussion ? 5963 @access private 5964 */ 5965 function get_all_args($acctnum='') 5966 { 5967 if ((!isset($acctnum)) 5968 || ((string)$acctnum == '')) 5969 { 5970 $acctnum = $this->get_acctnum(); 5971 } 5972 5973 if (isset($this->a[$acctnum]['args'])) 5974 { 5975 return $this->a[$acctnum]['args']; 5976 } 5977 else 5978 { 5979 // arg not set, or invalid input $arg_name 5980 return; 5981 } 5982 } 5983 5984 /*! 5985 @function unset_all_args 5986 @abstract ? 5987 @param $acctnum (int) optional 5988 @result none 5989 @author Angles 5990 @discussion ? 5991 @access private 5992 */ 5993 function unset_all_args($acctnum='') 5994 { 5995 if ((!isset($acctnum)) 5996 || ((string)$acctnum == '')) 5997 { 5998 $acctnum = $this->get_acctnum(); 5999 } 6000 6001 $this->a[$acctnum]['args'] = array(); 6002 } 6003 6004 6005 // depreciated 6006 //function get_folder($acctnum='') 6007 //{ 6008 // return $this->get_arg_value('folder'); 6009 //} 6010 6011 // depreciated 6012 //function get_msgnum($acctnum='') 6013 //{ 6014 // return $this->get_arg_value('["msgball"]["msgnum"]'); 6015 //} 6016 6017 //function get_pref_layout($acctnum='') 6018 //{ 6019 // return $this->get_pref_value('layout', $acctnum); 6020 //} 6021 6022 6023 } // end class mail_msg_wrappers 6024?> 6025