PhpFile::initFile()   B
last analyzed

Complexity

Conditions 7
Paths 10

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 8.3306
c 0
b 0
f 0
cc 7
nc 10
nop 1
1
<?php
2
/**
3
 * @author Threema GmbH
4
 * @copyright Copyright (c) 2015-2016 Threema GmbH
5
 */
6
7
8
namespace Threema\MsgApi\PublicKeyStores;
9
10
use Threema\Core\Exception;
11
use Threema\MsgApi\PublicKeyStore;
12
13
/**
14
 * Store the PublicKeys in a PHP file
15
 *
16
 * @package Threema\MsgApi\PublicKeyStores
17
 */
18
class PhpFile extends PublicKeyStore
19
{
20
	/**
21
	 * PHP code used to prevent unauthorized access
22
	 *
23
	 * @var string
24
	 */
25
	private $fileBlocker = '<?php if (!isset($isMsgApiKeystore) || !$isMsgApiKeystore) die(\'Unauthorized access\');';
26
27
	/**
28
	 * @var string
29
	 */
30
	private $file;
31
32
	/**
33
	 * cache of array
34
	 *
35
	 * @var array
36
	 */
37
	private $keystore = array();
38
39
	/**
40
	 * @param string $file path to a read and writable (empty) PHP file
41
	 * @throws Exception if the file does not exist, is not writable or no valid PHP file
42
	 */
43
	public function __construct($file)
44
	{
45
		if (false === is_writable($file)) {
46
			throw new Exception('file ' . $file . ' does not exist or is not writable');
47
		}
48
		if (pathinfo($file, PATHINFO_EXTENSION) != 'php') {
49
			throw new Exception('file ' . $file . ' is not a valid PHP file');
50
		}
51
		$this->file = $file;
52
	}
53
54
	/**
55
	 * return null if the public key not found in the store
56
	 *
57
	 * @param string $threemaId
58
	 * @return null|string
59
	 */
60
	public function findPublicKey($threemaId)
61
	{
62
		$threemaId = strtoupper($threemaId);
63
		$publicKey = null;
64
65
		//Pre-check loaded array
66
		if (array_key_exists($threemaId, $this->keystore)) {
67
			$publicKey = $this->keystore[$threemaId];
68
			return $publicKey;
69
		}
70
71
		//Parse file
72
		$keystore = array();
73
		$isMsgApiKeystore = true;
74
		require $this->file;
75
76
		//Update cache
77
		$this->keystore = $keystore;
78
79
		//Check file content
80
		if (array_key_exists($threemaId, $keystore)) {
81
			$publicKey = $keystore[$threemaId];
82
		}
83
84
		return $publicKey;
85
	}
86
87
	/**
88
	 * save a public key
89
	 *
90
	 * @param string $threemaId
91
	 * @param string $publicKey
92
	 * @throws Exception
93
	 * @return bool
94
	 */
95
	public function savePublicKey($threemaId, $publicKey)
96
	{
97
		//create file if needed
98
		$this->initFile();
99
100
		//check for key
101
		if (array_key_exists($threemaId, $this->keystore)) {
102
			return false;
103
		}
104
105
		//add key
106
		$this->keystore[$threemaId] = $publicKey;
107
		$content = '$keystore[\'' . $threemaId . '\'] = \'' . $publicKey . '\';' . PHP_EOL;
108
109
		//write content
110
		$fileadd = file_put_contents($this->file, $content, FILE_APPEND);
111
		if (!$fileadd) {
112
			throw new Exception('could not write to file ' . $this->file);
113
		}
114
115
		return true;
116
	}
117
118
	/**
119
	 * initiate a php file
120
	 *
121
	 * @param null|resource file handle for file opened in r+ mode
122
	 * @return bool
123
	 * @throws Exception
124
	 */
125
	private function initFile($fileHandle = null)
126
	{
127
		//check if file does already contain content
128
		if (filesize($this->file) != 0) {
129
			return true;
130
		}
131
132
		//manually open file if no file handle is given
133
		$fileopened = null;
134
		if (null === $fileHandle) {
135
			$fileHandle = fopen($this->file, 'r+');
136
			$fileopened = true;
137
138
			//check for success
139
			if (null === $fileHandle) {
140
				throw new Exception('could not open file ' . $this->file);
141
			}
142
		}
143
144
		//create content
145
		$content = $this->fileBlocker . PHP_EOL;
146
		$content .= PHP_EOL;
147
		$content .= '//Threema MsgApi phpfile keystore' . PHP_EOL;
148
		$content .= '//DO NOT EDIT THIS FILE!' . PHP_EOL;
149
		$content .= PHP_EOL;
150
151
		//write file
152
		$fwrite = fwrite($fileHandle, $content);
153
		if (!$fwrite) {
154
			throw new Exception('could not write to file ' . $this->file);
155
		}
156
157
		//close file if necessary
158
		if ($fileopened) {
159
			$fclose = fclose($fileHandle);
160
			if (!$fclose) {
161
				throw new Exception('error while processing file ' . $this->file);
162
			}
163
		}
164
		return true;
165
	}
166
167
	/**
168
	 * Initialize a new PhpFile Public Key Store
169
	 * @param string $path the file will be created if it does not exist
170
	 * @return PhpFile
171
	 */
172
	public static function create($path) {
173
		if(false === file_exists($path)) {
174
			//touch
175
			touch($path);
176
		}
177
178
		return new PhpFile($path);
179
	}
180
}
181