Issues (752)

server/includes/download_message.php (1 issue)

Labels
Severity
1
<?php
2
3
// required to handle php errors
4
require_once __DIR__ . '/exceptions/class.ZarafaErrorException.php';
5
require_once __DIR__ . '/download_base.php';
6
7
/**
8
 * DownloadMessage.
9
 *
10
 * A class to manage downloading of message as a file,
11
 * it will generate the message as RFC822-formatted e-mail stream.
12
 * It extends the DownloadBase class.
13
 */
14
class DownloadMessage extends DownloadBase {
15
	/**
16
	 * Function get message-stream using respective mapi function.
17
	 * It also sends the eml file to the client.
18
	 */
19
	public function downloadMessageAsFile() {
20
		if (!$this->message || !$this->store) {
21
			return;
22
		}
23
		// get message properties.
24
		$messageProps = mapi_getprops($this->message, [PR_SUBJECT, PR_MESSAGE_CLASS]);
25
26
		$stream = $this->getEmlStream($messageProps);
27
28
		$filename = (!empty($messageProps[PR_SUBJECT])) ? $messageProps[PR_SUBJECT] : _('Untitled');
29
		$filename .= '.eml';
30
31
		// Set the file length
32
		$stat = mapi_stream_stat($stream);
33
34
		$this->setNecessaryHeaders($filename, $stat['cb']);
35
36
		// Read whole message and echo it.
37
		for ($i = 0; $i < $stat['cb']; $i += BLOCK_SIZE) {
38
			// Print stream
39
			echo mapi_stream_read($stream, BLOCK_SIZE);
40
41
			// Need to discard the buffer contents to prevent memory
42
			// exhaustion while echoing large content.
43
			ob_flush();
44
		}
45
	}
46
47
	/**
48
	 * Function will create a ZIP archive and add eml files into the same.
49
	 * It also configures necessary header information which required to send the ZIP file to client.
50
	 * Send ZIP to the client if all the requested eml files included successfully into the same.
51
	 */
52
	public function downloadMessageAsZipFile() {
53
		if (!$this->store) {
54
			return;
55
		}
56
		// Generate random ZIP file name at default temporary path of PHP
57
		$randomZipName = tempnam(sys_get_temp_dir(), 'zip');
58
59
		// Create an open zip archive.
60
		$zip = new ZipArchive();
61
		$result = $zip->open($randomZipName, ZipArchive::CREATE);
62
63
		if ($result === true) {
64
			for ($index = 0, $count = count($this->entryIds); $index < $count; ++$index) {
65
				$this->message = mapi_msgstore_openentry($this->store, hex2bin((string) $this->entryIds[$index]));
66
67
				// get message properties.
68
				$messageProps = mapi_getprops($this->message, [PR_SUBJECT, PR_MESSAGE_CLASS]);
69
70
				$stream = $this->getEmlStream($messageProps);
71
				$stat = mapi_stream_stat($stream);
72
73
				// Get the stream
74
				$datastring = '';
75
				for ($i = 0; $i < $stat['cb']; $i += BLOCK_SIZE) {
76
					$datastring .= mapi_stream_read($stream, BLOCK_SIZE);
77
					// Need to discard the buffer contents to prevent memory
78
					// exhaustion.
79
					ob_flush();
80
				}
81
82
				$filename = (!empty($messageProps[PR_SUBJECT])) ? $messageProps[PR_SUBJECT] : _('Untitled');
83
				$filename .= '.eml';
84
85
				$filename = $this->handleDuplicateFileNames($filename);
86
				// Remove slashes to prevent unwanted directories to be created in the zip file.
87
				$filename = str_replace('\\', '_', $filename);
88
				$filename = str_replace('/', '_', $filename);
89
90
				// Add file into zip by stream
91
				$zip->addFromString($filename, $datastring);
92
			}
93
		}
94
		else {
95
			$zip->close();
96
			// Remove the zip file to avoid unnecessary disk-space consumption
97
			unlink($randomZipName);
98
99
			// Throw exception if ZIP is not created successfully
100
			throw new ZarafaException(_("ZIP is not created successfully"));
101
		}
102
103
		$zip->close();
104
105
		// Set the headers
106
		header('Pragma: public');
107
		header('Expires: 0'); // set expiration time
108
		header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
109
		header('Content-Disposition: attachment; filename="' . addslashes(browserDependingHTTPHeaderEncode(_("Messages") . date(" d-m-Y") . ".zip")) . '"');
110
		header('Content-Transfer-Encoding: binary');
111
		header('Content-Type:  application/zip');
112
		header('Content-Length: ' . filesize($randomZipName));
113
114
		// Send the actual response as ZIP file
115
		readfile($randomZipName);
116
117
		// Remove the zip file to avoid unnecessary disk-space consumption
118
		unlink($randomZipName);
119
	}
120
121
	/**
122
	 * Function will obtain stream from the message, For email messages it will open email as
123
	 * inet object and get the stream content as eml format, when user has IMAP enabled.
124
	 *
125
	 * @param array $messageProps properties of this particular message
126
	 *
127
	 * @return Stream $stream the eml stream obtained from message
0 ignored issues
show
The type Stream was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
128
	 */
129
	public function getEmlStream($messageProps) {
130
		// Get addressbook for current session
131
		$addrBook = $GLOBALS['mapisession']->getAddressbook();
132
133
		// Read the message as RFC822-formatted e-mail stream.
134
		$stream = mapi_inetmapi_imtoinet($GLOBALS['mapisession']->getSession(), $addrBook, $this->message, []);
135
136
		return $stream;
137
	}
138
139
	/**
140
	 * Check received data and decide either the eml file or
141
	 * ZIP file is requested to be downloaded.
142
	 */
143
	public function download() {
144
		if ($this->allAsZip) {
145
			// download multiple eml messages in a ZIP file
146
			$this->downloadMessageAsZipFile();
147
		}
148
		else {
149
			// download message as file
150
			$this->downloadMessageAsFile();
151
		}
152
	}
153
}
154
155
// create instance of class to download message as file
156
$messageInstance = new DownloadMessage();
157
158
try {
159
	// initialize variables
160
	$messageInstance->init($_GET);
161
162
	// download message
163
	$messageInstance->download();
164
}
165
catch (Exception $e) {
166
	$messageInstance->handleSaveMessageException($e);
167
}
168