Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  /**
   3   * Copyright 2011-2017 Horde LLC (http://www.horde.org/)
   4   *
   5   * See the enclosed file LICENSE for license information (LGPL). If you
   6   * did not receive this file, see http://www.horde.org/licenses/lgpl21.
   7   *
   8   * @category  Horde
   9   * @copyright 2011-2017 Horde LLC
  10   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  11   * @package   Imap_Client
  12   */
  13  
  14  /**
  15   * Object containing data returned by the Horde_Imap_Client_Base#fetch()
  16   * command.
  17   *
  18   * @author    Michael Slusarz <slusarz@horde.org>
  19   * @category  Horde
  20   * @copyright 2011-2017 Horde LLC
  21   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  22   * @package   Imap_Client
  23   */
  24  class Horde_Imap_Client_Data_Fetch
  25  {
  26      /** Header formatting constants. */
  27      const HEADER_PARSE = 1;
  28      const HEADER_STREAM = 2;
  29  
  30      /**
  31       * Internal data array.
  32       *
  33       * @var array
  34       */
  35      protected $_data = array();
  36  
  37      /**
  38       */
  39      public function __clone()
  40      {
  41          $this->_data = unserialize(serialize($this->_data));
  42      }
  43  
  44      /**
  45       * Set the full message property.
  46       *
  47       * @param mixed $msg  The full message text, as either a string or stream
  48       *                    resource.
  49       */
  50      public function setFullMsg($msg)
  51      {
  52          $this->_data[Horde_Imap_Client::FETCH_FULLMSG] = $this->_setMixed($msg);
  53      }
  54  
  55      /**
  56       * Returns the full message.
  57       *
  58       * @param boolean $stream  Return as a stream?
  59       *
  60       * @return mixed  The full text of the entire message.
  61       */
  62      public function getFullMsg($stream = false)
  63      {
  64          return $this->_msgText(
  65              $stream,
  66              isset($this->_data[Horde_Imap_Client::FETCH_FULLMSG])
  67                  ? $this->_data[Horde_Imap_Client::FETCH_FULLMSG]
  68                  : null
  69          );
  70      }
  71  
  72      /**
  73       * Set the message structure.
  74       *
  75       * @param Horde_Mime_Part $structure  The base MIME part of the message.
  76       */
  77      public function setStructure(Horde_Mime_Part $structure)
  78      {
  79          $this->_data[Horde_Imap_Client::FETCH_STRUCTURE] = $structure;
  80      }
  81  
  82      /**
  83       * Get the message structure.
  84       *
  85       * @return Horde_Mime_Part $structure  The base MIME part of the message.
  86       */
  87      public function getStructure()
  88      {
  89          return isset($this->_data[Horde_Imap_Client::FETCH_STRUCTURE])
  90              ? clone $this->_data[Horde_Imap_Client::FETCH_STRUCTURE]
  91              : new Horde_Mime_Part();
  92      }
  93  
  94      /**
  95       * Set a header entry.
  96       *
  97       * @param string $label  The search label.
  98       * @param mixed $data    Either a Horde_Mime_Headers object or the raw
  99       *                       header text.
 100       */
 101      public function setHeaders($label, $data)
 102      {
 103          if ($data instanceof Horde_Stream) {
 104              $data = $data->stream;
 105          }
 106          $this->_data[Horde_Imap_Client::FETCH_HEADERS][$label] = $data;
 107      }
 108  
 109      /**
 110       * Get a header entry.
 111       *
 112       * @param string $label    The search label.
 113       * @param integer $format  The return format. If self::HEADER_PARSE,
 114       *                         returns a Horde_Mime_Headers object. If
 115       *                         self::HEADER_STREAM, returns a stream.
 116       *                         Otherwise, returns header text.
 117       *
 118       * @return mixed  See $format.
 119       */
 120      public function getHeaders($label, $format = 0)
 121      {
 122          return $this->_getHeaders(
 123              $label,
 124              $format,
 125              Horde_Imap_Client::FETCH_HEADERS
 126          );
 127      }
 128  
 129      /**
 130       * Set a header text entry.
 131       *
 132       * @param string $id   The MIME ID.
 133       * @param mixed $text  The header text, as either a string or stream
 134       *                     resource.
 135       */
 136      public function setHeaderText($id, $text)
 137      {
 138          $this->_data[Horde_Imap_Client::FETCH_HEADERTEXT][$id] = $this->_setMixed($text);
 139      }
 140  
 141      /**
 142       * Get a header text entry.
 143       *
 144       * @param string $id       The MIME ID.
 145       * @param integer $format  The return format. If self::HEADER_PARSE,
 146       *                         returns a Horde_Mime_Headers object. If
 147       *                         self::HEADER_STREAM, returns a stream.
 148       *                         Otherwise, returns header text.
 149       *
 150       * @return mixed  See $format.
 151       */
 152      public function getHeaderText($id = 0, $format = 0)
 153      {
 154          return $this->_getHeaders(
 155              $id,
 156              $format,
 157              Horde_Imap_Client::FETCH_HEADERTEXT
 158          );
 159      }
 160  
 161      /**
 162       * Set a MIME header entry.
 163       *
 164       * @param string $id   The MIME ID.
 165       * @param mixed $text  The header text, as either a string or stream
 166       *                     resource.
 167       */
 168      public function setMimeHeader($id, $text)
 169      {
 170          $this->_data[Horde_Imap_Client::FETCH_MIMEHEADER][$id] = $this->_setMixed($text);
 171      }
 172  
 173      /**
 174       * Get a MIME header entry.
 175       *
 176       * @param string $id       The MIME ID.
 177       * @param integer $format  The return format. If self::HEADER_PARSE,
 178       *                         returns a Horde_Mime_Headers object. If
 179       *                         self::HEADER_STREAM, returns a stream.
 180       *                         Otherwise, returns header text.
 181       *
 182       * @return mixed  See $format.
 183       */
 184      public function getMimeHeader($id, $format = 0)
 185      {
 186          return $this->_getHeaders(
 187              $id,
 188              $format,
 189              Horde_Imap_Client::FETCH_MIMEHEADER
 190          );
 191      }
 192  
 193      /**
 194       * Set a body part entry.
 195       *
 196       * @param string $id      The MIME ID.
 197       * @param mixed $text     The body part text, as either a string or stream
 198       *                        resource.
 199       * @param string $decode  Either '8bit', 'binary', or null.
 200       */
 201      public function setBodyPart($id, $text, $decode = null)
 202      {
 203          $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id] = array(
 204              'd' => $decode,
 205              't' => $this->_setMixed($text)
 206          );
 207      }
 208  
 209      /**
 210       * Get a body part entry.
 211       *
 212       * @param string $id       The MIME ID.
 213       * @param boolean $stream  Return as a stream?
 214       *
 215       * @return mixed  The full text of the body part.
 216       */
 217      public function getBodyPart($id, $stream = false)
 218      {
 219          return $this->_msgText(
 220              $stream,
 221              isset($this->_data[Horde_Imap_Client::FETCH_BODYPART][$id])
 222                  ? $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]['t']
 223                  : null
 224          );
 225      }
 226  
 227      /**
 228       * Determines if/how a body part was MIME decoded on the server.
 229       *
 230       * @param string $id  The MIME ID.
 231       *
 232       * @return string  Either '8bit', 'binary', or null.
 233       */
 234      public function getBodyPartDecode($id)
 235      {
 236          return isset($this->_data[Horde_Imap_Client::FETCH_BODYPART][$id])
 237              ? $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id]['d']
 238              : null;
 239      }
 240  
 241      /**
 242       * Set the body part size for a body part.
 243       *
 244       * @param string $id     The MIME ID.
 245       * @param integer $size  The size (in bytes).
 246       */
 247      public function setBodyPartSize($id, $size)
 248      {
 249          $this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id] = intval($size);
 250      }
 251  
 252      /**
 253       * Returns the body part size, if returned by the server.
 254       *
 255       * @param string $id  The MIME ID.
 256       *
 257       * @return integer  The body part size, in bytes.
 258       */
 259      public function getBodyPartSize($id)
 260      {
 261          return isset($this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id])
 262              ? $this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id]
 263              : null;
 264      }
 265  
 266      /**
 267       * Set a body text entry.
 268       *
 269       * @param string $id   The MIME ID.
 270       * @param mixed $text  The body part text, as either a string or stream
 271       *                     resource.
 272       */
 273      public function setBodyText($id, $text)
 274      {
 275          $this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id] = $this->_setMixed($text);
 276      }
 277  
 278      /**
 279       * Get a body text entry.
 280       *
 281       * @param string $id       The MIME ID.
 282       * @param boolean $stream  Return as a stream?
 283       *
 284       * @return mixed  The full text of the body text.
 285       */
 286      public function getBodyText($id = 0, $stream = false)
 287      {
 288          return $this->_msgText(
 289              $stream,
 290              isset($this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id])
 291                  ? $this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id]
 292                  : null
 293          );
 294      }
 295  
 296      /**
 297       * Set envelope data.
 298       *
 299       * @param array $data  The envelope data to pass to the Envelope object
 300       *                     constructor, or an Envelope object.
 301       */
 302      public function setEnvelope($data)
 303      {
 304          $this->_data[Horde_Imap_Client::FETCH_ENVELOPE] = is_array($data)
 305              ? new Horde_Imap_Client_Data_Envelope($data)
 306              : $data;
 307      }
 308  
 309      /**
 310       * Get envelope data.
 311       *
 312       * @return Horde_Imap_Client_Data_Envelope  An envelope object.
 313       */
 314      public function getEnvelope()
 315      {
 316          return isset($this->_data[Horde_Imap_Client::FETCH_ENVELOPE])
 317              ? clone $this->_data[Horde_Imap_Client::FETCH_ENVELOPE]
 318              : new Horde_Imap_Client_Data_Envelope();
 319      }
 320  
 321      /**
 322       * Set IMAP flags.
 323       *
 324       * @param array $flags  An array of IMAP flags.
 325       */
 326      public function setFlags(array $flags)
 327      {
 328          $this->_data[Horde_Imap_Client::FETCH_FLAGS] = array_map(
 329              'Horde_String::lower',
 330              array_map('trim', $flags)
 331          );
 332      }
 333  
 334      /**
 335       * Get IMAP flags.
 336       *
 337       * @return array  An array of IMAP flags (all flags in lowercase).
 338       */
 339      public function getFlags()
 340      {
 341          return isset($this->_data[Horde_Imap_Client::FETCH_FLAGS])
 342              ? $this->_data[Horde_Imap_Client::FETCH_FLAGS]
 343              : array();
 344      }
 345  
 346      /**
 347       * Set IMAP internal date.
 348       *
 349       * @param mixed $date  Either a Horde_Imap_Client_DateTime object or a
 350       *                     date string.
 351       */
 352      public function setImapDate($date)
 353      {
 354          $this->_data[Horde_Imap_Client::FETCH_IMAPDATE] = is_object($date)
 355              ? $date
 356              : new Horde_Imap_Client_DateTime($date);
 357      }
 358  
 359      /**
 360       * Get internal IMAP date.
 361       *
 362       * @return Horde_Imap_Client_DateTime  A date object.
 363       */
 364      public function getImapDate()
 365      {
 366          return isset($this->_data[Horde_Imap_Client::FETCH_IMAPDATE])
 367              ? clone $this->_data[Horde_Imap_Client::FETCH_IMAPDATE]
 368              : new Horde_Imap_Client_DateTime();
 369      }
 370  
 371      /**
 372       * Set message size.
 373       *
 374       * @param integer $size  The size of the message, in bytes.
 375       */
 376      public function setSize($size)
 377      {
 378          $this->_data[Horde_Imap_Client::FETCH_SIZE] = intval($size);
 379      }
 380  
 381      /**
 382       * Get message size.
 383       *
 384       * @return integer  The size of the message, in bytes.
 385       */
 386      public function getSize()
 387      {
 388          return isset($this->_data[Horde_Imap_Client::FETCH_SIZE])
 389              ? $this->_data[Horde_Imap_Client::FETCH_SIZE]
 390              : 0;
 391      }
 392  
 393      /**
 394       * Set UID.
 395       *
 396       * @param integer $uid  The message UID.
 397       */
 398      public function setUid($uid)
 399      {
 400          $this->_data[Horde_Imap_Client::FETCH_UID] = intval($uid);
 401      }
 402  
 403      /**
 404       * Get UID.
 405       *
 406       * @return integer  The message UID.
 407       */
 408      public function getUid()
 409      {
 410          return isset($this->_data[Horde_Imap_Client::FETCH_UID])
 411              ? $this->_data[Horde_Imap_Client::FETCH_UID]
 412              : null;
 413      }
 414  
 415      /**
 416       * Set message sequence number.
 417       *
 418       * @param integer $seq  The message sequence number.
 419       */
 420      public function setSeq($seq)
 421      {
 422          $this->_data[Horde_Imap_Client::FETCH_SEQ] = intval($seq);
 423      }
 424  
 425      /**
 426       * Get message sequence number.
 427       *
 428       * @return integer  The message sequence number.
 429       */
 430      public function getSeq()
 431      {
 432          return isset($this->_data[Horde_Imap_Client::FETCH_SEQ])
 433              ? $this->_data[Horde_Imap_Client::FETCH_SEQ]
 434              : null;
 435      }
 436  
 437      /**
 438       * Set the modified sequence value for the message.
 439       *
 440       * @param integer $modseq  The modseq value.
 441       */
 442      public function setModSeq($modseq)
 443      {
 444          $this->_data[Horde_Imap_Client::FETCH_MODSEQ] = intval($modseq);
 445      }
 446  
 447      /**
 448       * Get the modified sequence value for the message.
 449       *
 450       * @return integer  The modseq value.
 451       */
 452      public function getModSeq()
 453      {
 454          return isset($this->_data[Horde_Imap_Client::FETCH_MODSEQ])
 455              ? $this->_data[Horde_Imap_Client::FETCH_MODSEQ]
 456              : null;
 457      }
 458  
 459      /**
 460       * Set the internationalized downgraded status for the message.
 461       *
 462       * @since 2.11.0
 463       *
 464       * @param boolean $downgraded  True if at least one message component has
 465       *                             been downgraded.
 466       */
 467      public function setDowngraded($downgraded)
 468      {
 469          if ($downgraded) {
 470              $this->_data[Horde_Imap_Client::FETCH_DOWNGRADED] = true;
 471          } else {
 472              unset($this->_data[Horde_Imap_Client::FETCH_DOWNGRADED]);
 473          }
 474      }
 475  
 476      /**
 477       * Does the message contain internationalized downgraded data (i.e. it
 478       * is a "surrogate" message)?
 479       *
 480       * @since 2.11.0
 481       *
 482       * @return boolean  True if at least one message components has been
 483       *                  downgraded.
 484       */
 485      public function isDowngraded()
 486      {
 487          return !empty($this->_data[Horde_Imap_Client::FETCH_DOWNGRADED]);
 488      }
 489  
 490      /**
 491       * Return the internal representation of the data.
 492       *
 493       * @return array  The data array.
 494       */
 495      public function getRawData()
 496      {
 497          return $this->_data;
 498      }
 499  
 500      /**
 501       * Merge a fetch object into this one.
 502       *
 503       * @param Horde_Imap_Client_Data_Fetch $data  A fetch object.
 504       */
 505      public function merge(Horde_Imap_Client_Data_Fetch $data)
 506      {
 507          $this->_data = array_replace_recursive(
 508              $this->_data,
 509              $data->getRawData()
 510          );
 511      }
 512  
 513      /**
 514       * Does this object containing cacheable data of the given type?
 515       *
 516       * @param integer $type  The type to query.
 517       *
 518       * @return boolean  True if the type is cacheable.
 519       */
 520      public function exists($type)
 521      {
 522          return isset($this->_data[$type]);
 523      }
 524  
 525      /**
 526       * Does this object contain only default values for all fields?
 527       *
 528       * @return boolean  True if object contains default data.
 529       */
 530      public function isDefault()
 531      {
 532          return empty($this->_data);
 533      }
 534  
 535      /**
 536       * Return text representation of a field.
 537       *
 538       * @param boolean $stream  Return as a stream?
 539       * @param mixed $data      The field data (string or resource) or null if
 540       *                         field does not exist.
 541       *
 542       * @return mixed  Requested text representation.
 543       */
 544      protected function _msgText($stream, $data)
 545      {
 546          if ($data instanceof Horde_Stream) {
 547              if ($stream) {
 548                  $data->rewind();
 549                  return $data->stream;
 550              }
 551              return strval($data);
 552          }
 553  
 554          if (is_resource($data)) {
 555              rewind($data);
 556              return $stream
 557                  ? $data
 558                  : stream_get_contents($data);
 559          }
 560  
 561          if (!$stream) {
 562              return strval($data);
 563          }
 564  
 565          $tmp = fopen('php://temp', 'w+');
 566  
 567          if (!is_null($data)) {
 568              fwrite($tmp, $data);
 569              rewind($tmp);
 570          }
 571  
 572          return $tmp;
 573      }
 574  
 575      /**
 576       * Return representation of a header field.
 577       *
 578       * @param string $id       The header id.
 579       * @param integer $format  The return format. If self::HEADER_PARSE,
 580       *                         returns a Horde_Mime_Headers object. If
 581       *                         self::HEADER_STREAM, returns a stream.
 582       *                         Otherwise, returns header text.
 583       * @param integer $key     The array key where the data is stored in the
 584       *                         internal array.
 585       *
 586       * @return mixed  The data in the format specified by $format.
 587       */
 588      protected function _getHeaders($id, $format, $key)
 589      {
 590          switch ($format) {
 591          case self::HEADER_STREAM:
 592              if (!isset($this->_data[$key][$id])) {
 593                  $data = null;
 594              } elseif (is_object($this->_data[$key][$id])) {
 595                  switch ($key) {
 596                  case Horde_Imap_Client::FETCH_HEADERS:
 597                      $data = $this->_getHeaders($id, 0, $key);
 598                      break;
 599  
 600                  case Horde_Imap_Client::FETCH_HEADERTEXT:
 601                  case Horde_Imap_Client::FETCH_MIMEHEADER:
 602                      $data = $this->_data[$key][$id];
 603                      break;
 604                  }
 605              } else {
 606                  $data = $this->_data[$key][$id];
 607              }
 608  
 609              return $this->_msgText(true, $data);
 610  
 611          case self::HEADER_PARSE:
 612              if (!isset($this->_data[$key][$id])) {
 613                  return new Horde_Mime_Headers();
 614              } elseif (is_object($this->_data[$key][$id])) {
 615                  switch ($key) {
 616                  case Horde_Imap_Client::FETCH_HEADERS:
 617                      return clone $this->_data[$key][$id];
 618  
 619                  case Horde_Imap_Client::FETCH_HEADERTEXT:
 620                  case Horde_Imap_Client::FETCH_MIMEHEADER:
 621                      return Horde_Mime_Headers::parseHeaders($this->_data[$key][$id]);
 622                  }
 623              } else {
 624                  $hdrs = $this->_getHeaders($id, self::HEADER_STREAM, $key);
 625                  $parsed = Horde_Mime_Headers::parseHeaders($hdrs);
 626                  fclose($hdrs);
 627                  return $parsed;
 628              }
 629          }
 630  
 631          if (!isset($this->_data[$key][$id])) {
 632              return '';
 633          }
 634  
 635          if (is_object($this->_data[$key][$id])) {
 636              switch ($key) {
 637              case Horde_Imap_Client::FETCH_HEADERS:
 638                  return $this->_data[$key][$id]->toString(
 639                      array('nowrap' => true)
 640                  );
 641  
 642              case Horde_Imap_Client::FETCH_HEADERTEXT:
 643              case Horde_Imap_Client::FETCH_MIMEHEADER:
 644                  return strval($this->_data[$key][$id]);
 645              }
 646          }
 647  
 648          return $this->_msgText(false, $this->_data[$key][$id]);
 649      }
 650  
 651      /**
 652       * Converts mixed input (string or resource) to the correct internal
 653       * representation.
 654       *
 655       * @param mixed $data  Mixed data (string, resource, Horde_Stream object).
 656       *
 657       * @return mixed  The internal representation of that data.
 658       */
 659      protected function _setMixed($data)
 660      {
 661          return is_resource($data)
 662              ? new Horde_Stream_Existing(array('stream' => $data))
 663              : $data;
 664      }
 665  
 666  }