1<?php
2
3/**
4 * DNS Library for handling lookups and updates.
5 *
6 * Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
7 *
8 * See LICENSE for more details.
9 *
10 * @category  Networking
11 * @package   Net_DNS2
12 * @author    Mike Pultz <mike@mikepultz.com>
13 * @copyright 2020 Mike Pultz <mike@mikepultz.com>
14 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
15 * @link      https://netdns2.com/
16 * @since     File available since Release 1.1.0
17 *
18 */
19
20/**
21 * File-based caching for the Net_DNS2_Cache class
22 *
23 */
24class Net_DNS2_Cache_File extends Net_DNS2_Cache
25{
26    /**
27     * open a cache object
28     *
29     * @param string  $cache_file path to a file to use for cache storage
30     * @param integer $size       the size of the shared memory segment to create
31     * @param string  $serializer the name of the cache serialize to use
32     *
33     * @throws Net_DNS2_Exception
34     * @access public
35     * @return void
36     *
37     */
38    public function open($cache_file, $size, $serializer)
39    {
40        $this->cache_size       = $size;
41        $this->cache_file       = $cache_file;
42        $this->cache_serializer = $serializer;
43
44        //
45        // check that the file exists first
46        //
47        if ( ($this->cache_opened == false)
48            && (file_exists($this->cache_file) == true)
49            && (filesize($this->cache_file) > 0)
50        ) {
51            //
52            // open the file for reading
53            //
54            $fp = @fopen($this->cache_file, 'r');
55            if ($fp !== false) {
56
57                //
58                // lock the file just in case
59                //
60                flock($fp, LOCK_EX);
61
62                //
63                // read the file contents
64                //
65                $data = fread($fp, filesize($this->cache_file));
66
67                $decoded = null;
68
69                if ($this->cache_serializer == 'json') {
70
71                    $decoded = json_decode($data, true);
72                } else {
73
74                    $decoded = unserialize($data);
75                }
76
77                if (is_array($decoded) == true) {
78
79                    $this->cache_data = $decoded;
80                } else {
81
82                    $this->cache_data = [];
83                }
84
85                //
86                // unlock
87                //
88                flock($fp, LOCK_UN);
89
90                //
91                // close the file
92                //
93                fclose($fp);
94
95                //
96                // clean up the data
97                //
98                $this->clean();
99
100                //
101                // mark this so we don't read this contents more than once per instance.
102                //
103                $this->cache_opened = true;
104            }
105        }
106    }
107
108    /**
109     * Destructor
110     *
111     * @access public
112     *
113     */
114    public function __destruct()
115    {
116        //
117        // if there's no cache file set, then there's nothing to do
118        //
119        if (strlen($this->cache_file) == 0) {
120            return;
121        }
122
123        //
124        // open the file for reading/writing
125        //
126        $fp = fopen($this->cache_file, 'a+');
127        if ($fp !== false) {
128
129            //
130            // lock the file just in case
131            //
132            flock($fp, LOCK_EX);
133
134            //
135            // seek to the start of the file to read
136            //
137            fseek($fp, 0, SEEK_SET);
138
139            //
140            // read the file contents
141            //
142            $data = @fread($fp, filesize($this->cache_file));
143            if ( ($data !== false) && (strlen($data) > 0) ) {
144
145                //
146                // unserialize and store the data
147                //
148                $c = $this->cache_data;
149
150                $decoded = null;
151
152                if ($this->cache_serializer == 'json') {
153
154                    $decoded = json_decode($data, true);
155                } else {
156
157                    $decoded = unserialize($data);
158                }
159
160                if (is_array($decoded) == true) {
161
162                    $this->cache_data = array_merge($c, $decoded);
163                }
164            }
165
166            //
167            // trucate the file
168            //
169            ftruncate($fp, 0);
170
171            //
172            // clean the data
173            //
174            $this->clean();
175
176            //
177            // resize the data
178            //
179            $data = $this->resize();
180            if (!is_null($data)) {
181
182                //
183                // write the file contents
184                //
185                fwrite($fp, $data);
186            }
187
188            //
189            // unlock
190            //
191            flock($fp, LOCK_UN);
192
193            //
194            // close the file
195            //
196            fclose($fp);
197        }
198    }
199}
200