Handler for message_part_structure hook.
Called for every part of the message.

@param array  Original parameters
@param string Part body (will be set if used internally)

@return array Modified parameters
541944
function part_structure($p, $body = null)
    {
        if ($p['mimetype'] == 'text/plain' || $p['mimetype'] == 'application/pgp') {
            $this->parse_plain($p, $body);
        }
        else if ($p['mimetype'] == 'multipart/signed') {
            $this->parse_signed($p, $body);
        }
        else if ($p['mimetype'] == 'multipart/encrypted') {
            $this->parse_encrypted($p);
        }
        else if ($p['mimetype'] == 'application/pkcs7-mime') {
            $this->parse_encrypted($p);
        }

        return $p;
    }
756158
protected function getPartBody(&$part)
    {
        $body = '';
        if ($this->stream) {
            $body = $this->getPartBodyFromFile($part);
        } elseif ($this->data) {
            $body = $this->getPartBodyFromText($part);
        }

        return $body;
    }
1144519
public function addPart(self $part = null): self
    {
        return $this->parts[] = $part === null ? new self : $part;
    }
1079201
private static function getBodyFromParts(array $parts, string $bodyMimeType)
    {
        foreach ($parts as $part) {
            if ($body = static::getBodyFromParts($part->getParts(), $bodyMimeType)) {
                return $body;
            }
            if (
                $part->getMimeType() === $bodyMimeType &&
                $part->getBody() instanceof \Google_Service_Gmail_MessagePartBody &&
                $body = static::bodyToText($part->getBody())
            ) {
                return $body;
            }
        }

        return;
    }
1189260
protected function bindPartConcat($var, ServerRequestInterface $request, array $parts, &$part)
    {
        if (!is_string($var) || $var[0] !== '~' || substr($var, -1) !== '~') {
            return false;
        }
        
        $pieces = array_map('trim', explode('~', substr($var, 1, -1)));
        $bound = array_filter($this->bind($pieces, $request, $parts));
        $part = [join('', $bound)];
        
        return true;
    }
426328
String parseBodyStructure(boolean includeExtension) {
        try {
            String fields = parseBodyFields();
            StringBuilder buf = new StringBuilder();
            buf.append(LB);
            if (primaryType.equalsIgnoreCase("Text")) {
                buf.append("\"TEXT\" \"");
                buf.append(secondaryType.toUpperCase());
                buf.append("\" ");
                buf.append(fields);
                buf.append(' ');
                buf.append(lineCount);

                // is:    * 1 FETCH (BODYSTRUCTURE ("Text" "plain" NIL NIL NIL NIL    4  -1))
                // wants: * 1 FETCH (BODYSTRUCTURE ("text" "plain" NIL NIL NIL "8bit" 6  1  NIL NIL NIL))
                // or:    * 1 FETCH (BODYSTRUCTURE ("text" "plain" NIL NIL NIL "7bit" 28 1 NIL NIL NIL))

            } else if (primaryType.equalsIgnoreCase(MESSAGE) && secondaryType.equalsIgnoreCase("rfc822")) {
                buf.append("\"MESSAGE\" \"RFC822\" ");
                buf.append(fields).append(SP);
//                setupLogger(parts[0]); // reset transient logger
                buf.append(parts[0].getEnvelope()).append(SP);
                buf.append(parts[0].getBodyStructure(false)).append(SP);
                buf.append(lineCount);
            } else if (primaryType.equalsIgnoreCase(MULTIPART)) {
                for (MailMessageAttributes part : parts) {
//                    setupLogger(parts[i]); // reset transient getLogger()
                    buf.append(part.getBodyStructure(includeExtension));
                }
                buf.append(SP + Q).append(secondaryType).append(Q);
            } else {
                //1. primary type -------
                buf.append('\"');
                buf.append(primaryType.toUpperCase());
                buf.append('\"');
                //2. sec type -------
                buf.append(" \"");
                buf.append(secondaryType.toUpperCase());
                buf.append('\"');
                //3. params -------
                buf.append(' ');
                getParameters(buf);
                //4. body id -------
                buf.append(' ');
                if (null != contentID ) {
                    buf.append(Q).append(contentID).append(Q);
                } else {
                    buf.append(NIL);
                }
                //5. content desc -------
                buf.append(' ');
                if (null != contentDesc) {
                    buf.append('\"');
                    buf.append(contentDesc);
                    buf.append('\"');
                } else {
                    buf.append(NIL);
                }
                //6. encoding -------
                buf.append(' ');
                if (null != contentEncoding) {
                    buf.append('\"');
                    buf.append(contentEncoding);
                    buf.append('\"');
                } else {
                    buf.append(NIL);
                }
                //7. size -------
                buf.append(' ');
                buf.append(size);
            }

            if (includeExtension) {
                //extension is different for multipart and single parts
                if (primaryType.equalsIgnoreCase(MULTIPART)) {
                    //8. ext1 params -------
                    buf.append(' ');
                    getParameters(buf);
                    //9. ext2 disposition -------
                    buf.append(' ');
                    if (null != contentDisposition) {
                        buf.append(contentDisposition);
                    } else {
                        buf.append(NIL);
                    }
                    //10. ext3 language -------
                    buf.append(' ');
                    buf.append(NIL);
                } else {
                    // ext1 md5 -------
                    buf.append(' ');
                    buf.append(NIL);
                    // ext2 disposition -------
                    buf.append(' ');
                    if (null != contentDisposition) {
                        buf.append(contentDisposition);
                    } else {
                        buf.append(NIL);
                    }
                    //ext3 language -------
                    buf.append(' ');
                    buf.append(NIL);
                }
            }

            buf.append(RB);
            return buf.toString();
        } catch (Exception e) {
            throw new IllegalStateException("Can not parse body structure", e);
        }
    }
655023
public function setSignature(Message $message, $body)
    {
        $signedPart = $message->getSignaturePart();
        if ($signedPart === null) {
            $signedPart = $this->partBuilderFactory->newPartBuilder($this->mimePartFactory)->createMessagePart();
            $message->addChild($signedPart);
        }
        $signedPart->setRawHeader(
            'Content-Type',
            $message->getHeaderParameter('Content-Type', 'protocol')
        );
        $signedPart->setContent($body);
    }
332893
private function get_part_body($msg, $part)
    {
        // @TODO: Handle big bodies using file handles

        // This is a special case when we want to get the whole body
        // using direct IMAP access, in other cases we prefer
        // rcube_message::get_part_body() as the body may be already in memory
        if (!$part->mime_id) {
            // fake the size which may be empty for multipart/* parts
            // otherwise get_message_part() below will fail
            if (!$part->size) {
                $reset = true;
                $part->size = 1;
            }

            $storage = $this->rc->get_storage();
            $body    = $storage->get_message_part($msg->uid, $part->mime_id, $part,
                null, null, true, 0, false);

            if ($reset) {
                $part->size = 0;
            }
        }
        else {
            $body = $msg->get_part_body($part->mime_id, false);

            // Convert charset to get rid of possible non-ascii characters (#5962)
            if ($part->charset && stripos($part->charset, 'ASCII') === false) {
                $body = rcube_charset::convert($body, $part->charset, 'US-ASCII');
            }
        }

        return $body;
    }
203833
public function assembleAttachmentBody()
    {
        $body = array();
        $body[] = "This is a multi-part message in MIME format.";
        $body[] = "--{$this->_uid}";
        $body[] = "Content-Type: text/html; charset=\"utf-8\"";
        $body[] = "Content-Transfer-Encoding: quoted-printable";
        $body[] = "";
        $body[] = quoted_printable_encode($this->_message);
        $body[] = "";
        $body[] = "--{$this->_uid}";

        foreach ($this->_attachments as $attachment) {
            $body[] = $this->getAttachmentMimeTemplate($attachment);
        }

        return implode(PHP_EOL, $body) . '--';
    }
175904
public function get(
        string $url,
        string $method,
        array $query = [],
        array $body = [],
        array $server = []
    ): array {
        $method = strtolower($method);
        $requestParts = $this->buildRequestParts(
            $url,
            $query,
            $body,
            $server
        );

        return $this->tryRequest(function () use ($method, $requestParts) {
            return $this
                ->httpAdapter
                ->getByRequestParts(
                    $this->host,
                    $method,
                    $requestParts
                );
        }, $this
            ->retryMap
            ->getRetry(
                $url,
                $method
            )
        );
    }
910588
private function get_mime_numbers(&$part)
    {
        if (strlen($part->mime_id))
            $this->mime_parts[$part->mime_id] = &$part;

        if (is_array($part->parts))
            for ($i=0; $i<count($part->parts); $i++)
                $this->get_mime_numbers($part->parts[$i]);
    }
59040
public function addChild(MessagePart $part, $position = null)
    {
        if ($part !== $this) {
            $part->parent = $this;
            array_splice(
                $this->children,
                ($position === null) ? count($this->children) : $position,
                0,
                [ $part ]
            );
            $this->onChange();
        }
    }
1097961
function message_load($p)
    {
        $this->message = $p['object'];

        // handle attachments vcard attachments
        foreach ((array)$this->message->attachments as $attachment) {
            if ($this->is_vcard($attachment)) {
                $this->vcard_parts[] = $attachment->mime_id;
            }
        }
        // the same with message bodies
        foreach ((array)$this->message->parts as $part) {
            if ($this->is_vcard($part)) {
                $this->vcard_parts[]  = $part->mime_id;
                $this->vcard_bodies[] = $part->mime_id;
            }
        }

        if ($this->vcard_parts) {
            $this->add_texts('localization');
        }
    }
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";
  }
717939
protected function parseRouteParam($part, $targetPart)
    {
        preg_match('/\[(d|s)(?:\:([0-9a-zA-Z]*))?\]/', $part, $matches);

        $value = null;
        
        // If the part is a data type we need this route parameter
        if ($matches[1] === 'd' && is_numeric($targetPart)) {
            // Transform the value into the correct data type
            $value = $targetPart * 1;
        } else if ($matches[1] === 's' && is_string($targetPart)) {
            $value = $targetPart;
        }
        
        $key = '';
        if (isset($matches[2])) {
            $key = $matches[2];
        }
        
        return [$key, $value];
    }
801237
public function resolve($part, $source)
    {
        if (is_array($source)) {
            $source = $this->handleArray($part, $source);
        } elseif (is_object($source)) {
            $source = $this->handleObject($part, $source);
        }

        return $source;
    }
158069
public function parse(MimePart $part)
    {
        if (!$this->middleware) {
            return $part;
        }
        $part = call_user_func(array($this->middleware, 'parse'), $part, $this->next);
        return $part;
    }