Fetch the Message attachment

@param object $structure
@param mixed  $partNumber

@throws Exceptions\ConnectionFailedException
7929
protected function fetchAttachment($structure, $partNumber) {

        $oAttachment = new Attachment($this, $structure, $partNumber);

        if ($oAttachment->getName() !== null) {
            if ($oAttachment->getId() !== null) {
                $this->attachments->put($oAttachment->getId(), $oAttachment);
            } else {
                $this->attachments->push($oAttachment);
            }
        }
    }
201343
private function build_message($part) {
    $message = $part[ "message"];
    // #### only base64 encoding supported
    // #### other encodings you have to encode yourself
    if ($part[ "encode"] == "base64"){
      $message = chunk_split(base64_encode($message));
    }else if ($part[ "encode"] == "quoted-printable"){
      $message = $this->encode_qp($message);
    }
    return  "Content-Type: ".$part[ "ctype"].
            ($part[ "charset"]? "; charset = \"".$part[ "charset"]. "\"" :  "").
            ($part[ "name"]? "; name = \"".$part[ "name"]. "\"" :  "").
            (empty($part[ "encode"])? "" : "\nContent-Transfer-Encoding: ".$part[ "encode"] ).
            (empty($part[ "contentid"])? "" : "\nContent-ID: ".$part[ "contentid"] ).
            ((empty($part["contentid"])&&($part["name"]))? "\nContent-Disposition: attachment; filename=\"".$part["name"].'"' : '' ).
            "\n\n$message\n";
  }
372994
private function failsHeaderFor(MessagePart $part, $type, $name, $header)
    {
        $headerValue = null;
        
        static $map = [
            'content-type' => 'getContentType',
            'content-disposition' => 'getContentDisposition',
            'content-transfer-encoding' => 'getContentTransferEncoding',
            'content-id' => 'getContentId'
        ];
        $lower = strtolower($name);
        if (isset($map[$lower])) {
            $headerValue = call_user_func([$part, $map[$lower]]);
        } elseif (!($part instanceof MimePart)) {
            return ($type === static::FILTER_INCLUDE);
        } else {
            $headerValue = $part->getHeaderValue($name);
        }
        
        return (($type === static::FILTER_EXCLUDE && strcasecmp($headerValue, $header) === 0)
            || ($type === static::FILTER_INCLUDE && strcasecmp($headerValue, $header) !== 0));
    }
1183388
public function filter(MessagePart $part)
    {
        return !($this->failsMultiPartFilter($part)
            || $this->failsTextPartFilter($part)
            || $this->failsSignedPartFilter($part)
            || $this->failsHeaderPartFilter($part));
    }
1117819
function tnef_decode(&$part)
    {
        // @TODO: attachment may be huge, handle body via file
        $body     = $this->get_part_body($part->mime_id);
        $tnef     = new rcube_tnef_decoder;
        $tnef_arr = $tnef->decompress($body);
        $parts    = array();

        unset($body);

        foreach ($tnef_arr as $pid => $winatt) {
            $tpart = new rcube_message_part;

            $tpart->filename        = $this->fix_attachment_name(trim($winatt['name']), $part);
            $tpart->encoding        = 'stream';
            $tpart->ctype_primary   = trim(strtolower($winatt['type']));
            $tpart->ctype_secondary = trim(strtolower($winatt['subtype']));
            $tpart->mimetype        = $tpart->ctype_primary . '/' . $tpart->ctype_secondary;
            $tpart->mime_id         = 'winmail.' . $part->mime_id . '.' . $pid;
            $tpart->size            = $winatt['size'];
            $tpart->body            = $winatt['stream'];

            $parts[] = $tpart;
            unset($tnef_arr[$pid]);
        }

        return $parts;
    }
861750
public function fetchPartHeader($mailbox, $id, $is_uid = false, $part = null)
    {
        $part = empty($part) ? 'HEADER' : $part.'.MIME';

        return $this->handlePartBody($mailbox, $id, $is_uid, $part);
    }
311279
protected static function calculateFieldPathsAsArray(array $structure, string $firstLevelFieldName = null): array
    {
        $fieldPaths = [];
        foreach ($structure as $key => $subStructure) {
            $fieldPath = [];
            if ($firstLevelFieldName !== null) {
                $fieldPath[] = $firstLevelFieldName;
            }
            $fieldPath[] = $key;
            if (is_array($subStructure)) {
                foreach (self::calculateFieldPathsAsArray($subStructure) as $subFieldPath) {
                    $fieldPaths[] = array_merge($fieldPath, $subFieldPath);
                }
            } else {
                $fieldPaths[] = $fieldPath;
            }
        }

        return $fieldPaths;
    }
392620
public function save( & $structure )
    {
        if ( ! $structure instanceof Structure\ProxyAbstract ||
             empty( $structure->type ) )
        {
            return 0;
        }

        $data   = ArrayUtils::iteratorToArray( $structure->getBaseIterator() );
        $result = parent::save( $data );

        if ( $result > 0 )
        {
            if ( empty( $structure->id ) )
            {
                $structure->setOption( 'id', $id = $data['id'] );
            }
            else
            {
                $id = $structure->id;
            }

            foreach ( $structure->getPropertiesIterator() as $property => $value )
            {
                $result += $this->saveProperty(
                    $id, $structure::isPropertyLocaleAware( $property ),
                    $property, $value
                );
            }

            $tags = (array) $structure->getTags();
            $result += $this->deleteTagsNotIn( $id, $tags );

            foreach ( $tags as $tag )
            {
                $result += $this->setTagFor( $id, $tag );
            }
        }

        foreach ( $structure->getDependentStructures() as $depStruct )
        {
            if ( empty( $depStruct ) )
            {
                continue;
            }

            if ( $depStruct instanceof MapperAwareAbstract )
            {
                $result += $depStruct->save();
            }
            else if ( $depStruct instanceof MapperAwareInterface )
            {
                $result += $depStruct->getMapper()
                                     ->save( $depStruct );
            }
        }

        return $result;
    }
1198140
public function getStructureNodeRelatedByStructureNodeId(ConnectionInterface $con = null)
    {
        if ($this->aStructureNodeRelatedByStructureNodeId === null && ($this->structure_node_id !== null)) {
            $this->aStructureNodeRelatedByStructureNodeId = ChildStructureNodeQuery::create()->findPk($this->structure_node_id, $con);
            /* The following can be used additionally to
                guarantee the related object contains a reference
                to this object.  This level of coupling may, however, be
                undesirable since it could result in an only partially populated collection
                in the referenced object.
                $this->aStructureNodeRelatedByStructureNodeId->addStructureNodeParentsRelatedByStructureNodeId($this);
             */
        }

        return $this->aStructureNodeRelatedByStructureNodeId;
    }
60767
public function getAttachmentPart($index)
    {
        $attachments = $this->getAllAttachmentParts();
        if (!isset($attachments[$index])) {
            return null;
        }
        return $attachments[$index];
    }
695565
public void addPart(AttachmentPart part) {
        if (attachments == null) {
            attachments = new BodyPart.Attachments();
        }

        this.attachments.add(part);
    }
594824
private function failsMultiPartFilter(MessagePart $part)
    {
        if (!($part instanceof MimePart)) {
            return $this->multipart !== static::FILTER_EXCLUDE;
        }
        return ($this->multipart === static::FILTER_EXCLUDE && $part->isMultiPart())
            || ($this->multipart === static::FILTER_INCLUDE && !$part->isMultiPart());
    }
848614
@Override
    public InputStream getPart(String partName) throws IOException {
        ServletRESTRequestImpl ret = castRequest();
        if (ret != null)
            return ret.getPart(partName);
        return null;
    }
645974
protected function lazyLoadStructure(): void
    {
        if (true === $this->structureLoaded) {
            return;
        }
        $this->structureLoaded = true;

        $messageNumber = $this->getNumber();

        $errorMessage = null;
        $errorNumber  = 0;
        \set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber) {
            $errorMessage = $message;
            $errorNumber = $nr;
        });

        $structure = \imap_fetchstructure(
            $this->resource->getStream(),
            $messageNumber,
            \FT_UID
        );

        \restore_error_handler();

        if (!$structure instanceof \stdClass) {
            throw new MessageStructureException(\sprintf(
                'Message "%s" structure is empty: %s',
                $messageNumber,
                $errorMessage
            ), $errorNumber);
        }

        $this->setStructure($structure);
    }
147351
protected function getAttachmentStream(&$part)
    {
        /** @var resource $temp_fp */
        $temp_fp = tmpfile();

        $headers = $this->getPart('headers', $part);
        $encodingType = array_key_exists('content-transfer-encoding', $headers) ?
            $headers['content-transfer-encoding'] : '';

        if ($temp_fp) {
            if ($this->stream) {
                $start = $part['starting-pos-body'];
                $end = $part['ending-pos-body'];
                fseek($this->stream, $start, SEEK_SET);
                $len = $end - $start;
                $written = 0;
                while ($written < $len) {
                    $write = $len;
                    $data = fread($this->stream, $write);
                    fwrite($temp_fp, $this->decodeContentTransfer($data, $encodingType));
                    $written += $write;
                }
            } elseif ($this->data) {
                $attachment = $this->decodeContentTransfer($this->getPartBodyFromText($part), $encodingType);
                fwrite($temp_fp, $attachment, strlen($attachment));
            }
            fseek($temp_fp, 0, SEEK_SET);
        } else {
            throw new Exception(
                'Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.'
            );
        }

        return $temp_fp;
    }
263633
private function failsTextPartFilter(MessagePart $part)
    {
        return ($this->textpart === static::FILTER_EXCLUDE && $part->isTextPart())
            || ($this->textpart === static::FILTER_INCLUDE && !$part->isTextPart());
    }
563674
public static long getLastByteInPart(AmazonS3 s3, GetObjectRequest getObjectRequest, Integer partNumber) {
        ValidationUtils.assertNotNull(s3, "S3 client");
        ValidationUtils.assertNotNull(getObjectRequest, "GetObjectRequest");
        ValidationUtils.assertNotNull(partNumber, "partNumber");

        ObjectMetadata metadata = s3.getObjectMetadata(new GetObjectMetadataRequest(getObjectRequest.getBucketName(), getObjectRequest.getKey(), getObjectRequest.getVersionId())
                .withSSECustomerKey(getObjectRequest.getSSECustomerKey())
                .withPartNumber(partNumber));
        return metadata.getContentRange()[1];
    }