Version Description
- The required WordPress version changed to 3.2 and higher.
- Use plain text file as answer file (again). This time, hash value generated with hash_hmac() is stored in the file.
Download this release
Release Info
Developer | takayukister |
Plugin | Really Simple CAPTCHA |
Version | 1.5 |
Comparing to | |
See all releases |
Code changes from version 1.4 to 1.5
- readme.txt +12 -7
- really-simple-captcha.php +249 -199
readme.txt
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: takayukister
|
3 |
Donate link: http://contactform7.com/donate/
|
4 |
Tags: captcha
|
5 |
-
Requires at least: 2
|
6 |
Tested up to: 3.3.1
|
7 |
-
Stable tag: 1.
|
8 |
|
9 |
Really Simple CAPTCHA is a CAPTCHA module intended to be called from other plugins. It is originally created for my Contact Form 7 plugin.
|
10 |
|
@@ -18,9 +18,9 @@ Note: This product is "really simple" as its name suggests, i.e., it is not stro
|
|
18 |
|
19 |
Really Simple CAPTCHA does not use PHP "Sessions" for storing states, unlike many other PHP CAPTCHA solutions, but stores them as temporary files. This allows you to embed it into WordPress without worrying about conflicts.
|
20 |
|
21 |
-
When you generate a CAPTCHA, Really Simple CAPTCHA creates two files for it; one is an image file of CAPTCHA, and the other is a
|
22 |
|
23 |
-
The two files have the same (random) prefix in their file names, for example, "a7hk3ux8p.png" and "a7hk3ux8p.
|
24 |
|
25 |
= How to use with your plugin =
|
26 |
|
@@ -41,7 +41,7 @@ Generate a random word for CAPTCHA.
|
|
41 |
|
42 |
$word = $captcha_instance->generate_random_word();
|
43 |
|
44 |
-
Generate an image file and a
|
45 |
|
46 |
$prefix = mt_rand();
|
47 |
$captcha_instance->generate_image( $prefix, $word );
|
@@ -54,7 +54,7 @@ Check the correctness of the answer.
|
|
54 |
|
55 |
If the $correct is true, go ahead. Otherwise, block the respondent -- as it would appear not to be human.
|
56 |
|
57 |
-
And last, remove the temporary image and
|
58 |
|
59 |
$captcha_instance->remove( $prefix );
|
60 |
|
@@ -89,6 +89,11 @@ If you have any further questions, please submit them [to the support forum](htt
|
|
89 |
|
90 |
== Changelog ==
|
91 |
|
|
|
|
|
|
|
|
|
|
|
92 |
= 1.4 =
|
93 |
|
94 |
* Reverted answer file to PHP. As plain text file is visible from client side, that's not good.
|
@@ -102,4 +107,4 @@ If you have any further questions, please submit them [to the support forum](htt
|
|
102 |
|
103 |
= 1.1 =
|
104 |
* The required WordPress version changed to 2.8 and higher.
|
105 |
-
*
|
2 |
Contributors: takayukister
|
3 |
Donate link: http://contactform7.com/donate/
|
4 |
Tags: captcha
|
5 |
+
Requires at least: 3.2
|
6 |
Tested up to: 3.3.1
|
7 |
+
Stable tag: 1.5
|
8 |
|
9 |
Really Simple CAPTCHA is a CAPTCHA module intended to be called from other plugins. It is originally created for my Contact Form 7 plugin.
|
10 |
|
18 |
|
19 |
Really Simple CAPTCHA does not use PHP "Sessions" for storing states, unlike many other PHP CAPTCHA solutions, but stores them as temporary files. This allows you to embed it into WordPress without worrying about conflicts.
|
20 |
|
21 |
+
When you generate a CAPTCHA, Really Simple CAPTCHA creates two files for it; one is an image file of CAPTCHA, and the other is a text file which stores the correct answer to the CAPTCHA.
|
22 |
|
23 |
+
The two files have the same (random) prefix in their file names, for example, "a7hk3ux8p.png" and "a7hk3ux8p.txt." In this case, for example, when the respondent answers "K5GF" as an answer to the "a7hk3ux8p.png" image, then Really Simple CAPTCHA calculates hash of "K5GF" and tests it against the hash stored in the "a7hk3ux8p.txt" file. If the two match, the answer is confirmed as correct.
|
24 |
|
25 |
= How to use with your plugin =
|
26 |
|
41 |
|
42 |
$word = $captcha_instance->generate_random_word();
|
43 |
|
44 |
+
Generate an image file and a corresponding text file in the temporary directory.
|
45 |
|
46 |
$prefix = mt_rand();
|
47 |
$captcha_instance->generate_image( $prefix, $word );
|
54 |
|
55 |
If the $correct is true, go ahead. Otherwise, block the respondent -- as it would appear not to be human.
|
56 |
|
57 |
+
And last, remove the temporary image and text files, as they are no longer in use.
|
58 |
|
59 |
$captcha_instance->remove( $prefix );
|
60 |
|
89 |
|
90 |
== Changelog ==
|
91 |
|
92 |
+
= 1.5 =
|
93 |
+
|
94 |
+
* The required WordPress version changed to 3.2 and higher.
|
95 |
+
* Use plain text file as answer file (again). This time, hash value generated with hash_hmac() is stored in the file.
|
96 |
+
|
97 |
= 1.4 =
|
98 |
|
99 |
* Reverted answer file to PHP. As plain text file is visible from client side, that's not good.
|
107 |
|
108 |
= 1.1 =
|
109 |
* The required WordPress version changed to 2.8 and higher.
|
110 |
+
* cleanup() method added.
|
really-simple-captcha.php
CHANGED
@@ -1,200 +1,250 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
Plugin Name: Really Simple CAPTCHA
|
4 |
-
Plugin URI: http://ideasilo.wordpress.com/2009/03/14/really-simple-captcha/
|
5 |
-
Description: Really Simple CAPTCHA is a CAPTCHA module intended to be called from other plugins. It is originally created for my Contact Form 7 plugin.
|
6 |
-
Author: Takayuki Miyoshi
|
7 |
-
Version: 1.
|
8 |
-
Author URI: http://ideasilo.wordpress.com/
|
9 |
-
*/
|
10 |
-
|
11 |
-
/* Copyright 2007-2012 Takayuki Miyoshi (email: takayukister at gmail.com)
|
12 |
-
|
13 |
-
This program is free software; you can redistribute it and/or modify
|
14 |
-
it under the terms of the GNU General Public License as published by
|
15 |
-
the Free Software Foundation; either version 2 of the License, or
|
16 |
-
(at your option) any later version.
|
17 |
-
|
18 |
-
This program is distributed in the hope that it will be useful,
|
19 |
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21 |
-
GNU General Public License for more details.
|
22 |
-
|
23 |
-
You should have received a copy of the GNU General Public License
|
24 |
-
along with this program; if not, write to the Free Software
|
25 |
-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
26 |
-
*/
|
27 |
-
|
28 |
-
class ReallySimpleCaptcha {
|
29 |
-
|
30 |
-
function ReallySimpleCaptcha() {
|
31 |
-
|
32 |
-
/* Characters available in images */
|
33 |
-
$this->chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
34 |
-
|
35 |
-
/* Length of a word in an image */
|
36 |
-
$this->char_length = 4;
|
37 |
-
|
38 |
-
/* Array of fonts. Randomly picked up per character */
|
39 |
-
$this->fonts = array(
|
40 |
-
dirname( __FILE__ ) . '/gentium/GenAI102.TTF',
|
41 |
-
dirname( __FILE__ ) . '/gentium/GenAR102.TTF',
|
42 |
-
dirname( __FILE__ ) . '/gentium/GenI102.TTF',
|
43 |
-
dirname( __FILE__ ) . '/gentium/GenR102.TTF' );
|
44 |
-
|
45 |
-
/* Directory temporary keeping CAPTCHA images and corresponding
|
46 |
-
$this->tmp_dir = dirname( __FILE__ ) . '/tmp/';
|
47 |
-
|
48 |
-
/* Array of CAPTCHA image size. Width and height */
|
49 |
-
$this->img_size = array( 72, 24 );
|
50 |
-
|
51 |
-
/* Background color of CAPTCHA image. RGB color 0-255 */
|
52 |
-
$this->bg = array( 255, 255, 255 );
|
53 |
-
|
54 |
-
/* Foreground (character) color of CAPTCHA image. RGB color 0-255 */
|
55 |
-
$this->fg = array( 0, 0, 0 );
|
56 |
-
|
57 |
-
/* Coordinates for a text in an image. I don't know the meaning. Just adjust. */
|
58 |
-
$this->base = array( 6, 18 );
|
59 |
-
|
60 |
-
/* Font size */
|
61 |
-
$this->font_size = 14;
|
62 |
-
|
63 |
-
/* Width of a character */
|
64 |
-
$this->font_char_width = 15;
|
65 |
-
|
66 |
-
/* Image type. 'png', 'gif' or 'jpeg' */
|
67 |
-
$this->img_type = 'png';
|
68 |
-
|
69 |
-
/* Mode of temporary files */
|
70 |
-
$this->file_mode =
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
$
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
$filename = sanitize_file_name( $prefix . '.
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
$
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
?>
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: Really Simple CAPTCHA
|
4 |
+
Plugin URI: http://ideasilo.wordpress.com/2009/03/14/really-simple-captcha/
|
5 |
+
Description: Really Simple CAPTCHA is a CAPTCHA module intended to be called from other plugins. It is originally created for my Contact Form 7 plugin.
|
6 |
+
Author: Takayuki Miyoshi
|
7 |
+
Version: 1.5
|
8 |
+
Author URI: http://ideasilo.wordpress.com/
|
9 |
+
*/
|
10 |
+
|
11 |
+
/* Copyright 2007-2012 Takayuki Miyoshi (email: takayukister at gmail.com)
|
12 |
+
|
13 |
+
This program is free software; you can redistribute it and/or modify
|
14 |
+
it under the terms of the GNU General Public License as published by
|
15 |
+
the Free Software Foundation; either version 2 of the License, or
|
16 |
+
(at your option) any later version.
|
17 |
+
|
18 |
+
This program is distributed in the hope that it will be useful,
|
19 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21 |
+
GNU General Public License for more details.
|
22 |
+
|
23 |
+
You should have received a copy of the GNU General Public License
|
24 |
+
along with this program; if not, write to the Free Software
|
25 |
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
26 |
+
*/
|
27 |
+
|
28 |
+
class ReallySimpleCaptcha {
|
29 |
+
|
30 |
+
function ReallySimpleCaptcha() {
|
31 |
+
|
32 |
+
/* Characters available in images */
|
33 |
+
$this->chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
34 |
+
|
35 |
+
/* Length of a word in an image */
|
36 |
+
$this->char_length = 4;
|
37 |
+
|
38 |
+
/* Array of fonts. Randomly picked up per character */
|
39 |
+
$this->fonts = array(
|
40 |
+
dirname( __FILE__ ) . '/gentium/GenAI102.TTF',
|
41 |
+
dirname( __FILE__ ) . '/gentium/GenAR102.TTF',
|
42 |
+
dirname( __FILE__ ) . '/gentium/GenI102.TTF',
|
43 |
+
dirname( __FILE__ ) . '/gentium/GenR102.TTF' );
|
44 |
+
|
45 |
+
/* Directory temporary keeping CAPTCHA images and corresponding text files */
|
46 |
+
$this->tmp_dir = dirname( __FILE__ ) . '/tmp/';
|
47 |
+
|
48 |
+
/* Array of CAPTCHA image size. Width and height */
|
49 |
+
$this->img_size = array( 72, 24 );
|
50 |
+
|
51 |
+
/* Background color of CAPTCHA image. RGB color 0-255 */
|
52 |
+
$this->bg = array( 255, 255, 255 );
|
53 |
+
|
54 |
+
/* Foreground (character) color of CAPTCHA image. RGB color 0-255 */
|
55 |
+
$this->fg = array( 0, 0, 0 );
|
56 |
+
|
57 |
+
/* Coordinates for a text in an image. I don't know the meaning. Just adjust. */
|
58 |
+
$this->base = array( 6, 18 );
|
59 |
+
|
60 |
+
/* Font size */
|
61 |
+
$this->font_size = 14;
|
62 |
+
|
63 |
+
/* Width of a character */
|
64 |
+
$this->font_char_width = 15;
|
65 |
+
|
66 |
+
/* Image type. 'png', 'gif' or 'jpeg' */
|
67 |
+
$this->img_type = 'png';
|
68 |
+
|
69 |
+
/* Mode of temporary image files */
|
70 |
+
$this->file_mode = 0444;
|
71 |
+
|
72 |
+
/* Mode of temporary answer text files */
|
73 |
+
$this->answer_file_mode = 0440;
|
74 |
+
}
|
75 |
+
|
76 |
+
/* Generate and return random word with $chars characters x $char_length length */
|
77 |
+
|
78 |
+
function generate_random_word() {
|
79 |
+
$word = '';
|
80 |
+
|
81 |
+
for ( $i = 0; $i < $this->char_length; $i++ ) {
|
82 |
+
$pos = mt_rand( 0, strlen( $this->chars ) - 1 );
|
83 |
+
$char = $this->chars[$pos];
|
84 |
+
$word .= $char;
|
85 |
+
}
|
86 |
+
|
87 |
+
return $word;
|
88 |
+
}
|
89 |
+
|
90 |
+
/* Generate CAPTCHA code and corresponding code and save them into $tmp_dir directory.
|
91 |
+
$prefix is file prefix for both files.
|
92 |
+
$captcha is a random word usually generated by generate_random_word()
|
93 |
+
This function returns the filename of the CAPTCHA image temporary file */
|
94 |
+
|
95 |
+
function generate_image( $prefix, $word ) {
|
96 |
+
$dir = trailingslashit( $this->tmp_dir );
|
97 |
+
$filename = null;
|
98 |
+
|
99 |
+
if ( $im = imagecreatetruecolor( $this->img_size[0], $this->img_size[1] ) ) {
|
100 |
+
$bg = imagecolorallocate( $im, $this->bg[0], $this->bg[1], $this->bg[2] );
|
101 |
+
$fg = imagecolorallocate( $im, $this->fg[0], $this->fg[1], $this->fg[2] );
|
102 |
+
|
103 |
+
imagefill( $im, 0, 0, $bg );
|
104 |
+
|
105 |
+
$x = $this->base[0] + mt_rand( -2, 2 );
|
106 |
+
|
107 |
+
for ( $i = 0; $i < strlen( $word ); $i++ ) {
|
108 |
+
$font = $this->fonts[array_rand( $this->fonts )];
|
109 |
+
imagettftext( $im, $this->font_size, mt_rand( -2, 2 ), $x,
|
110 |
+
$this->base[1] + mt_rand( -2, 2 ), $fg, $font, $word[$i] );
|
111 |
+
$x += $this->font_char_width;
|
112 |
+
}
|
113 |
+
|
114 |
+
switch ( $this->img_type ) {
|
115 |
+
case 'jpeg':
|
116 |
+
$filename = sanitize_file_name( $prefix . '.jpeg' );
|
117 |
+
imagejpeg( $im, $dir . $filename );
|
118 |
+
break;
|
119 |
+
case 'gif':
|
120 |
+
$filename = sanitize_file_name( $prefix . '.gif' );
|
121 |
+
imagegif( $im, $dir . $filename );
|
122 |
+
break;
|
123 |
+
case 'png':
|
124 |
+
default:
|
125 |
+
$filename = sanitize_file_name( $prefix . '.png' );
|
126 |
+
imagepng( $im, $dir . $filename );
|
127 |
+
}
|
128 |
+
|
129 |
+
imagedestroy( $im );
|
130 |
+
@chmod( $dir . $filename, $this->file_mode );
|
131 |
+
}
|
132 |
+
|
133 |
+
$this->generate_answer_file( $prefix, $word );
|
134 |
+
|
135 |
+
return $filename;
|
136 |
+
}
|
137 |
+
|
138 |
+
/* Generate answer file corresponding to CAPTCHA image. */
|
139 |
+
|
140 |
+
function generate_answer_file( $prefix, $word ) {
|
141 |
+
$dir = trailingslashit( $this->tmp_dir );
|
142 |
+
$answer_file = $dir . sanitize_file_name( $prefix . '.txt' );
|
143 |
+
|
144 |
+
if ( $fh = fopen( $answer_file, 'w' ) ) {
|
145 |
+
$word = strtoupper( $word );
|
146 |
+
$salt = wp_generate_password( 64 );
|
147 |
+
$hash = hash_hmac( 'md5', $word, $salt );
|
148 |
+
|
149 |
+
$code = $salt . '|' . $hash;
|
150 |
+
|
151 |
+
fwrite( $fh, $code );
|
152 |
+
fclose( $fh );
|
153 |
+
}
|
154 |
+
|
155 |
+
@chmod( $answer_file, $this->answer_file_mode );
|
156 |
+
}
|
157 |
+
|
158 |
+
/* Check a $response against the code kept in the temporary file with $prefix
|
159 |
+
Return true if the two match, otherwise return false. */
|
160 |
+
|
161 |
+
function check( $prefix, $response ) {
|
162 |
+
$response = strtoupper( $response );
|
163 |
+
|
164 |
+
$dir = trailingslashit( $this->tmp_dir );
|
165 |
+
$filename = sanitize_file_name( $prefix . '.txt' );
|
166 |
+
$file = $dir . $filename;
|
167 |
+
|
168 |
+
if ( is_readable( $file ) && ( $code = file_get_contents( $file ) ) ) {
|
169 |
+
$code = explode( '|', $code, 2 );
|
170 |
+
|
171 |
+
$salt = $code[0];
|
172 |
+
$hash = $code[1];
|
173 |
+
|
174 |
+
if ( hash_hmac( 'md5', $response, $salt ) == $hash )
|
175 |
+
return true;
|
176 |
+
}
|
177 |
+
|
178 |
+
return false;
|
179 |
+
}
|
180 |
+
|
181 |
+
/* Remove temporary files with $prefix */
|
182 |
+
|
183 |
+
function remove( $prefix ) {
|
184 |
+
$suffixes = array( '.jpeg', '.gif', '.png', '.php', '.txt' );
|
185 |
+
|
186 |
+
foreach ( $suffixes as $suffix ) {
|
187 |
+
$filename = sanitize_file_name( $prefix . $suffix );
|
188 |
+
$file = trailingslashit( $this->tmp_dir ) . $filename;
|
189 |
+
if ( is_file( $file ) )
|
190 |
+
unlink( $file );
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
/* Clean up dead files older than $minutes in the tmp folder */
|
195 |
+
|
196 |
+
function cleanup( $minutes = 60 ) {
|
197 |
+
$dir = trailingslashit( $this->tmp_dir );
|
198 |
+
|
199 |
+
if ( ! is_dir( $dir ) || ! is_readable( $dir ) || ! is_writable( $dir ) )
|
200 |
+
return false;
|
201 |
+
|
202 |
+
$count = 0;
|
203 |
+
|
204 |
+
if ( $handle = @opendir( $dir ) ) {
|
205 |
+
while ( false !== ( $filename = readdir( $handle ) ) ) {
|
206 |
+
if ( ! preg_match( '/^[0-9]+\.(php|txt|png|gif|jpeg)$/', $filename ) )
|
207 |
+
continue;
|
208 |
+
|
209 |
+
$file = $dir . $filename;
|
210 |
+
|
211 |
+
$stat = @stat( $file );
|
212 |
+
if ( ( $stat['mtime'] + $minutes * 60 ) < time() ) {
|
213 |
+
@unlink( $file );
|
214 |
+
$count += 1;
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
closedir( $handle );
|
219 |
+
}
|
220 |
+
|
221 |
+
return $count;
|
222 |
+
}
|
223 |
+
|
224 |
+
/* Make a temporary directory and generate .htaccess file in it */
|
225 |
+
|
226 |
+
function make_tmp_dir() {
|
227 |
+
$dir = trailingslashit( $this->tmp_dir );
|
228 |
+
|
229 |
+
if ( ! wp_mkdir_p( $dir ) )
|
230 |
+
return false;
|
231 |
+
|
232 |
+
$htaccess_file = $dir . '.htaccess';
|
233 |
+
|
234 |
+
if ( file_exists( $htaccess_file ) )
|
235 |
+
return true;
|
236 |
+
|
237 |
+
if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
|
238 |
+
fwrite( $handle, 'Order deny,allow' . "\n" );
|
239 |
+
fwrite( $handle, 'Deny from all' . "\n" );
|
240 |
+
fwrite( $handle, '<Files ~ "^[0-9A-Za-z]+\\.(jpeg|gif|png)$">' . "\n" );
|
241 |
+
fwrite( $handle, ' Allow from all' . "\n" );
|
242 |
+
fwrite( $handle, '</Files>' . "\n" );
|
243 |
+
fclose( $handle );
|
244 |
+
}
|
245 |
+
|
246 |
+
return true;
|
247 |
+
}
|
248 |
+
}
|
249 |
+
|
250 |
?>
|