Overview

Namespaces

  • BSN
    • CryptUser

Classes

  • CryptJSONSource
  • CryptMySQLSource
  • CryptUser
  • SSLKey

Interfaces

  • CryptDataSource
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /*
  3: * Copyright (C) 2013 Bryan Nielsen - All Rights Reserved
  4: *
  5: * Author: Bryan Nielsen (bnielsen1965@gmail.com)
  6: *
  7: *
  8: * This file is part of cryptUser.
  9: * cryptUser is free software: you can redistribute it and/or modify
 10: * it under the terms of the GNU General Public License as published by
 11: * the Free Software Foundation, either version 3 of the License, or
 12: * (at your option) any later version.
 13: * 
 14: * cryptUser is distributed in the hope that it will be useful,
 15: * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17: * GNU General Public License for more details.
 18: * 
 19: * You should have received a copy of the GNU General Public License
 20: * along with cryptUser.  If not, see <http://www.gnu.org/licenses/>.
 21: */
 22: 
 23: namespace BSN\CryptUser;
 24: use Exception;
 25: 
 26: require_once 'CryptDataSource.php';
 27: 
 28: /**
 29:  * A JSON file based data source object for the CryptUsers.
 30:  *
 31:  * @author Bryan Nielsen, bnielsen1965@gmail.com
 32:  * @copyright Copyright 2013, Bryan Nielsen
 33:  */
 34: class CryptJSONSource implements CryptDataSource {
 35:     private $filename;
 36:     private $lockedFilePointer; // pointer to the currently open locked file
 37:     private $lockedFilename; // filename for the currently open locked file
 38:     
 39:     
 40:     /**
 41:      * Constructor to set up the data source
 42:      * 
 43:      */
 44:     public function __construct($filename) {
 45:         // reset locked file values
 46:         $this->lockedFilePointer = NULL;
 47:         $this->lockedFilename = '';
 48:         
 49:         $this->filename = $filename;
 50:         
 51:         // read file to test file locking
 52:         $this->readJSONFile();
 53:     }
 54:     
 55:     
 56:     /**
 57:      * Get source type
 58:      * 
 59:      * @return string The data source type.
 60:      */
 61:     public function getSourceType() {
 62:         return 'JSON';
 63:     }
 64:     
 65:     
 66:     /**
 67:      * Get array of users that match a given name.
 68:      * @param string $username The username to search for in the data source.
 69:      * @return array|boolean An array of arrays containing user elements to create a user
 70:      * or FALSE if not found.
 71:      */
 72:     public function getUserByName($username) {
 73:         // read the JSON file
 74:         $users = $this->readJSONFile($this->filename);
 75:         
 76:         if ($users) {
 77:             foreach ($users as $user) {
 78:                 if ($user['username'] == $username) return $user;
 79:             }
 80:         }
 81:         
 82:         // failed to find user
 83:         return FALSE;
 84:     }
 85:     
 86:     
 87:     /**
 88:      * Get a list of usernames
 89:      * @return array An array of strings containing the usernames from the data source.
 90:      */
 91:     public function getUsernames() {
 92:         $users = $this->readJSONFile($this->filename);
 93:         
 94:         if ($users) {
 95:             $usernames = array();
 96:             
 97:             foreach ($users as $user) {
 98:                 $usernames[] = $user['username'];
 99:             }
100:             
101:             return $usernames;
102:         }
103:         else return FALSE;
104:     }
105:     
106:     
107:     /**
108:      * Save the provided user details in the data source.
109:      * @param array $user An array of user elements to be saved.
110:      * @return boolean Returns TRUE on success and FALSE on failure.
111:      */
112:     public function saveUser($user) {
113:         // read the JSON file
114:         $users = $this->readJSONFile($this->filename);
115:         
116:         // determine if user exists
117:         if (($ui = $this->searchUsersForUser($users, $user['username'])) !== FALSE) {
118:             // found user index, update user
119:             $users[$ui] = $user;
120:         }
121:         else {
122:             // user not found, add to users
123:             $users[] = $user;
124:         }
125:         
126:         return $this->writeJSONFile($users, $this->filename);
127:     }
128:     
129:     
130:     /**
131:      * Delete the specified user from the data source.
132:      * @param string $username The username of the user to delete.
133:      * @return boolean Returns TRUE on success and FALSE on failure.
134:      */
135:     public function deleteUser($username) {
136:         // read the JSON file
137:         $users = $this->readJSONFile($this->filename);
138:         
139:         // find the index to the specified user
140:         $userIndex = $this->searchUsersForUser($users, $username);
141:         
142:         if ($userIndex !== FALSE) {
143:             // remove the user from the list
144:             unset($users[$userIndex]);
145:             
146:             // save the list
147:             return $this->writeJSONFile($users, $this->filename);
148:         }
149:         else {
150:             return FALSE;
151:         }
152:     }
153:     
154:     
155:     /**
156:      * Search provided users array for the specified user.
157:      * @param array $users An array of user rows to search.
158:      * @return integer|boolean The array index for the user name or FALSE if not found.
159:      */
160:     private function searchUsersForUser($users, $username) {
161:         if ($users) {
162:             foreach ($users as $ui => $user) {
163:                 if ($user['username'] == $username) return $ui;
164:             }
165:         }
166:         
167:         return FALSE;
168:     }
169:     
170:     
171:     
172:     
173:     /**
174:      * Read a JSON formatted file using the file locking mechanism and return as an 
175:      * associative array
176:      * 
177:      * @param string $filename Optional filename of the JSON file to write. If not
178:      * specified then the objects filename setting will be used.
179:      * @return array | boolean An associative array or FALSE on failure.
180:      */
181:     public function readJSONFile($filename = NULL) {
182:         // use this source filename if not provided
183:         if (empty($filename)) $filename = $this->filename;
184:         
185:         // read the JSON file
186:         $stringJSON = $this->lockedRead($filename);
187:         $arrayJSON = json_decode($stringJSON, TRUE);
188:         return $arrayJSON;
189:     }
190:     
191:     
192:     /**
193:      * Write a JSON formatted file using the file locking mechanism. The provided 
194:      * data array or object element will be used for the file contents.
195:      * 
196:      * @param array | object $data An associative array or object to convert to JSON.
197:      * @param string $filename Optional filename of the JSON file to write. If not
198:      * specified then the objects filename setting will be used.
199:      * @return boolean TRUE on success, FALSE on failure.
200:      */
201:     public function writeJSONFile($data, $filename = NULL) {
202:         // use this source filename if not provided
203:         if (empty($filename)) $filename = $this->filename;
204:         
205:         // save the JSON data to the file
206:         return $this->lockedWrite($this->filename, json_encode($data));
207:     }
208: 
209:     
210:     /**
211:     * Open and lock a file for both read and write operations.
212:     *
213:     * @param filename Filename of file to open and lock.
214:     * @param createIfNotExist Optional boolean to specify if the file should be created if it does not exist.
215:     * @return boolean Open status.
216:     * @throws Exception If cannot get lock on file for any reason.
217:     */
218:     public function lockFile($filename, $createIfNotExist = TRUE) {
219:         // check to see if opening a new file
220:         if ($filename != $this->lockedFilename || empty($this->lockedFilePointer)) {
221:             // create file if it does not exist
222:             if ($createIfNotExist && !file_exists($filename)) touch($filename);
223:         
224:             // if file pointer is already open then close
225:             if ($this->lockedFilePointer) {
226:                 flock($this->lockedFilePointer, LOCK_UN);
227:                 fclose($this->lockedFilePointer);
228:                 $this->lockedFilePointer = NULL;
229:                 $this->lockedFilename = '';
230:             }
231:             
232:             // open the file
233:             $this->lockedFilePointer = fopen($filename, 'r+');
234:             
235:             // try to get exclusive lock on the file
236:             if ($this->lockedFilePointer && flock($this->lockedFilePointer, LOCK_EX)) {
237:                 $this->lockedFilename = $filename;
238:             }
239:             else {
240:                 // lock failed
241:                 $this->lockedFilePointer = NULL;
242:                 $this->lockedFilename = '';
243:                 
244:                 throw new Exception("Failed to get the lock on file!");
245:             }
246:         }
247:     }
248:     
249:     
250:     /**
251:     * Read file with lock.
252:     *
253:     * @param filename Filename of file to read.
254:     * @param createIfNotExist Optional boolean to specify if the file should be created if it does not exist.
255:     * @return string or boolean Returns file contents in a string or FALSE on failure.
256:     * @throws Exception If for any reason the file is not locked.
257:     */
258:     public function lockedRead($filename, $createIfNotExist = TRUE) {
259:         // make sure file is opened and locked
260:         $this->lockFile($filename, $createIfNotExist);
261:         
262:         // if we have the file locked then read
263:         if( $this->lockedFilePointer ) {
264:             // make sure we are at beginning of file
265:             fseek($this->lockedFilePointer, 0);
266:             
267:             // read lines from the file
268:             $buffer = '';
269:             while ($line = fgets($this->lockedFilePointer)) {
270:                 $buffer .= $line;
271:             }
272:             
273:             // return buffer
274:             return $buffer;
275:         }
276:         else {
277:             throw new Exception("Failed to get the lock on file!");
278:         }
279:     }
280:     
281:     
282:     /**
283:     * Write buffer to file with lock
284:     *
285:     * @param string $filename The filename to write.
286:     * @param string $buffer The buffer to write to the file.
287:     * @param boolean $createIfNotExist Optional, specifies if the file should be 
288:     * created if it does not already exist.
289:     * @return boolean FALSE if write fails
290:     * @throws Exception If for any reason the file is not locked.
291:     */
292:     public function lockedWrite($filename, $buffer, $createIfNotExist = TRUE) {
293:         // make sure file is opened and locked
294:         $this->lockFile($filename, $createIfNotExist);
295:         
296:         // if we have the file locked then write
297:         if( $this->lockedFilePointer ) {
298:             // make sure we are at beginning of file
299:             fseek($this->lockedFilePointer, 0);
300:             
301:             // erase file using truncate
302:             ftruncate($this->lockedFilePointer, 0);
303:             
304:             // write buffer
305:             fwrite($this->lockedFilePointer, $buffer);
306:             fflush($this->lockedFilePointer);
307:             
308:             // return success
309:             return TRUE;
310:         }
311:         else {
312:             throw new Exception("Failed to get the lock on file!");
313:         }
314:     }
315:     
316:     
317:     /**
318:      * The magic __wakeup() function is used to clean up the file pointers when
319:      * the object is unserialized.
320:      */
321:     public function __wakeup() {
322:         // if file pointer is already open then close
323:         if ($this->lockedFilePointer) {
324:             $this->lockedFilePointer = NULL;
325:         }
326:     }
327: }
328: 
329: 
cryptUser API documentation generated by ApiGen 2.8.0