Render attachments into the given content.

@param string &$content
@param string $boundary
@throws MailException
761541
private function renderAttachments(&$content, $boundary)
    {
        foreach($this->attachments as $file => $name) {
            if (!is_readable($file)) {
                throw new MailException('File could not be read: ' . $file); // @codeCoverageIgnore
            }
            $data = chunk_split(base64_encode(file_get_contents($file)));
            $type = mime_content_type($file);
            $content .= "\r\n";
            $content .= "--$boundary\r\n";
            $content .= "Content-Type: $type;\r\n\tname=\"$name\"\r\n";
            $content .= "Content-Transfer-Encoding: base64\r\n";
            $content .= "Content-Description: \"$name\"\r\n";
            $content .= "Content-Disposition: attachment;\r\n\tfilename=\"$name\"\r\n";
            $content .= "\r\n";
            $content .= "$data";
        }
    }
785534
@Override
	public void setContent(final Object content, final String type) throws MessagingException
	{
		charset = EmailExtensions.getCharsetFromContentType(type);
		super.setContent(content, type);
	}
372008
public static function renderAs($data, string $content_type, array $options = []) {
		// clena up output buffer
		\Helper\Ob::cleanAll();
		Application::set('flag.global.__content_type', $content_type);
		Application::set('flag.global.__skip_layout', 1);
		header("Content-type: " . $content_type);
		if (!empty($options['output_file_name'])) {
			header('Content-Disposition: attachment; filename=' . $options['output_file_name']);
		}
		$options['extension'] = ($options['extension'] ?? '');
		switch ($content_type . $options['extension']) {
			case 'application/json':
				echo json_encode($data);
				break;
			case 'application/xml':
				if (is_array($data)) {
					echo array2xml($data);
				} else {
					echo $data;
				}
				break;
			case 'text/html':
				\Helper\Ob::start();
				require(Application::get(['application', 'path_full']) . 'Layout/blank.html');
				echo str_replace([
					'<!-- [numbers: document title] -->',
					'<!-- [numbers: document body] -->'
				], [
					\Layout::renderDocumentTitle(),
					$data
				], \Helper\Ob::clean());
				break;
			case 'text/htmlemail':
				\Helper\Ob::start();
				require(Application::get(['application', 'path_full']) . 'Layout/' . \Application::get('application.layout.email') . '.html');
				echo str_replace([
					'<!-- [numbers: document title] -->',
					'<!-- [numbers: document body] -->'
				], [
					'<title>' . ($options['title'] ?? '') . '</title>',
					$data
				], \Helper\Ob::clean());
				break;
			case 'text/htmlplain':
			default:
				echo $data;
		}
		exit;
	}
386718
protected function writeFile(string $filename, string $content): void
    {
        try {
            $f = \fopen($filename, 'w');
            \fwrite($f, $content, \mb_strlen($content));
            \fclose($f);
        } catch (\Throwable $e) {
            throw new WriterException($e->getMessage(), $e->getCode(), $e);
        }
    }
1005045
protected function processEndCondition(string &$content): void
    {
        $pattern = $this->getTagPattern(preg_quote('/', '/') . '(if|loop)');
        $content = preg_replace_callback($pattern, function ($match) {
            return '<?php } ?>';
        }, $content);
    }
707255
private function renderTextAndHtmlWithEmbededFiles(&$content, $text, $html, $encoding, $boundary)
    {
        $uid = uniqid();
        $boundary2 = "x----_=_NextPart_002_$uid";
        $content .= "\r\n--$boundary\r\n";
        $content .= "Content-Type: multipart/related;\r\n\tboundary=\"$boundary2\";\r\n\ttype=\"multipart/alternative\"\r\n";
        $this->renderTextAndHtml($content, $text, $html, $encoding, $boundary2);
        $this->renderEmbeddedFiles($content, $boundary2);
        $content .= "\r\n--$boundary2--\r\n";
    }
391353
private function renderContent(Content $content)
    {
        $tpl = $content->has('template') ? " <comment>($content->template)</comment>" : "";
        $this->app->writeln("Rendering: <info>{$content->target}</info>{$tpl}");

        // Only template files are run through Twig (template can be "none")
        if ($content->has('template'))
        {
            if ($content->paginate) {
                return $this->paginate($content);
            }
            else {
                $html = $this->twig->render($content->id, [
                    'page' => $content,
                    'posts' => $this->getPosts($content),
                    'parent' => $this->getParent($content->parentId)
                ]);
            }
        }
        else {
            $template = $this->twig->createTemplate($content->content);
            $html = $template->render([]);
        }

        // Save Content
        $this->savePage($content->target, $html);
    }
949729
protected function sendHeader($header, $content)
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }
1097311
public function addAttachment(string $file, string $content = null, string $contentType = null): MimePart
    {
        return $this->attachments[] = $this->createAttachment($file, $content, $contentType, 'attachment');
    }
606074
protected function processIncludeTag(string &$content): void
    {
        $pattern = $this->getTagPattern('include\s+(.+?)');
        while (preg_match($pattern, $content) != 0) {
            $content = preg_replace_callback($pattern, function ($match) {
                $viewResult = new ViewResult($match[1]);
                return $viewResult->getTemplateSource();
            }, $content);
        }
    }
893076
protected function processBlocks(string &$content): void
    {
        $pattern = $this->getTagPattern('block\s+([_a-zA-Z][_a-zA-Z0-9]*)' . preg_quote($this->endTag, '/') . '\s*(.+?)\s*' . preg_quote($this->startTag . '/block', '/'));
        $blockCodes = [];
        $content = preg_replace_callback($pattern, function ($match) use (&$blockCodes) {
            $blockCodes[$match[1]] = $match[2];
            return '';
        }, $content);
        $displayPattern = $this->getTagPattern('display_block\s+([_a-zA-Z][_a-zA-Z0-9]*)');
        $content = preg_replace_callback($displayPattern, function ($match) use ($blockCodes) {
            if (isset($blockCodes[$match[1]])) {
                return $blockCodes[$match[1]];
            }
            return '';
        }, $content);
    }
1173685
private function renderIncludeForContent(Content $content, $fileName, $parameters)
    {
        $directory       = dirname($fileName);
        $baseName        = basename($fileName);
        $realContentPath = realpath($this->contentPath);

        // Including a file from current directory
        if($directory == '.')
        {
            $realDirectory = realpath($this->contentPath . DIRECTORY_SEPARATOR . dirname($content->getPath()));
        }
        // Include a file based on relative path
        elseif($directory[0] == '.')
        {
            $realDirectory = realpath($this->contentPath . DIRECTORY_SEPARATOR . dirname($content->getPath()) . DIRECTORY_SEPARATOR . $directory);
        }
        // Including a file based on absolute path
        else
        {
            $realDirectory = realpath($this->contentPath . DIRECTORY_SEPARATOR . $directory);
        }

        if(strcmp($realContentPath, $realDirectory) <= 0)
        {
            $fullPath = $realDirectory . DIRECTORY_SEPARATOR . $baseName;
            if(file_exists($fullPath))
            {
                $type = pathinfo($fullPath, PATHINFO_EXTENSION);
                return $this->render(new Content($type, substr($fullPath, strlen($realContentPath))), $parameters);
            }

            throw new \InvalidArgumentException("Include file [$fullPath] does not exist.");
        }

        throw new \InvalidArgumentException($content->getPath() . "Unable to render [$realDirectory/$fileName]. It is outside of allowed content root path [$realContentPath].");
    }
164259
public Map<String, Object> readMultipartData(String boundary) throws IOException {
		// Boundaries are '--' + the boundary.
		boundary = "--" + boundary;
		// Form data
		Map<String, Object> form = new HashMap<String, Object>();
		// Implementation of a reader to parse out form boundaries.
		MultipartReader reader = new MultipartReader(input, boundary);
		String l;
		while ((l = reader.readLine()) != null) {
			if (!l.startsWith(boundary) || l.startsWith(boundary) && l.endsWith("--")) {
				break;
			}
			// Read headers
			Map<String, String> props = new HashMap<String, String>();
			while ((l = reader.readLine()) != null && l.trim().length() > 0) {
				// Properties
				String key = HttpUtil.capitalizeHeader(l.substring(0, l.indexOf(':')));
				String value = l.substring(l.indexOf(':') + 1);
				if (value.charAt(0) == ' ')
					value = value.substring(1);

				props.put(key, value);
			}
			// Check if the line STILL isn't null
			if (l != null) {
				String contentDisposition = props.get(HttpHeader.CONTENT_DISPOSITION);
				Map<String, String> disposition = new HashMap<String, String>();
				String[] dis = contentDisposition.split("; ");
				for (String s : dis) {
					int eqIdx = s.indexOf('=');
					if (eqIdx != -1) {
						String key = s.substring(0, eqIdx);
						String value = s.substring(eqIdx + 1).trim();
						if (value.charAt(0) == '"') {
							value = value.substring(1, value.length() - 1);
						}
						disposition.put(key, value);
					}
				}
				String name = disposition.get("name");
				if (props.containsKey(HttpHeader.CONTENT_TYPE)) {
					String fileName = disposition.get("filename");
					// Create a temporary file, this'll hopefully be deleted
					// when the request object has finalize() called
					File tmp = File.createTempFile("upload", fileName);
					// Open an output stream to the new file
					FileOutputStream output = new FileOutputStream(tmp);
					// Read the file data right from the connection, NO MEMORY
					// CACHE.
					byte[] buffer = new byte[1024];
					while (true) {
						int read = reader.readUntilBoundary(buffer, 0, buffer.length);
						if (read == -1) {
							break;
						}
						output.write(buffer, 0, read);
					}
					// Close it
					output.close();
					// Put the temp file
					form.put(name, new HttpFileUpload(fileName, tmp));
				} else {
					String value = "";
					// String value
					while ((l = reader.readLineUntilBoundary()) != null) {
						value += l;
					}
					form.put(name, value);
				}
			}
		}
		return form;
	}
1349400
public function echoPdfContent($content, $filename, $download = false)
    {
        // \MUtil_Echo::track($filename);
        if ($download) {
            // Download & save
			header('Content-Type: application/x-download');
        } else {
            //We send to a browser
            header('Content-Type: application/pdf');
        }
        header('Content-Length: '.strlen($content));
        header('Content-Disposition: inline; filename="'.$filename.'"');
        header('Cache-Control: private, max-age=0, must-revalidate');
        header('Pragma: public');

        echo $content;
    }
306573
public function html($content, $param = [], $config = [])
    {
        if ($param) {
            $content = strtr($content, $this->parseParam($param, $config));
        }
        $this->message->setBody($content, MailerConfig::CONTENT_HTML);

        return $this;
    }
972904
public function display($content, $data = []) {
        $this->content = $content;

        extract($data, EXTR_OVERWRITE);
        eval('?>' . $this->content);
    }
853584
private function renderHtml(&$content, $html, $encoding, $boundary)
    {
        $content .= "\r\n";
        $content .= "--$boundary\r\n";
        $content .= "Content-Type: text/html;\r\n\tcharset=\"$encoding\"\r\n";
        $content .= "Content-Transfer-Encoding: quoted-printable\r\n";
        $content .= "\r\n";
        $content .= "$html\r\n";
    }