[PHP-CVS] svn: /php/php-src/trunk/ext/gd/ gd.c gd_ctx.c libgd/gd_io.h

2011-01-03 Thread Pierre Joye
pajoye   Mon, 03 Jan 2011 09:22:58 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307018

Log:
- stream output support for image outputs functions

Changed paths:
U   php/php-src/trunk/ext/gd/gd.c
U   php/php-src/trunk/ext/gd/gd_ctx.c
U   php/php-src/trunk/ext/gd/libgd/gd_io.h

Modified: php/php-src/trunk/ext/gd/gd.c
===
--- php/php-src/trunk/ext/gd/gd.c   2011-01-03 07:24:19 UTC (rev 307017)
+++ php/php-src/trunk/ext/gd/gd.c   2011-01-03 09:22:58 UTC (rev 307018)
@@ -2821,7 +2821,8 @@
 #if HAVE_GD_BUNDLED
 PHP_FUNCTION(imagexbm)
 {
-   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_XBM, XBM, gdImageXbmCtx);
+// _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_XBM, XBM, gdImageXbmCtx);
+   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_XBM, GIF, gdImageXbmCtx);
 }
 #endif
 /* }}} */
@@ -2831,11 +2832,7 @@
Output GIF image to browser or file */
 PHP_FUNCTION(imagegif)
 {
-#ifdef HAVE_GD_GIF_CTX
_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_GIF, GIF, gdImageGifCtx);
-#else
-   _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, 
GIF, gdImageGif);
-#endif
 }
 /* }}} */
 #endif /* HAVE_GD_GIF_CREATE */
@@ -2845,11 +2842,7 @@
Output PNG image to browser or file */
 PHP_FUNCTION(imagepng)
 {
-#ifdef USE_GD_IOCTX
-   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_PNG, PNG, gdImagePngCtxEx);
-#else
-   _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, 
PNG, gdImagePng);
-#endif
+   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_PNG, GIF, gdImagePngCtxEx);
 }
 /* }}} */
 #endif /* HAVE_GD_PNG */
@@ -2860,11 +2853,7 @@
Output PNG image to browser or file */
 PHP_FUNCTION(imagewebp)
 {
-#ifdef USE_GD_IOCTX
-   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_WEBP, WEBP, gdImageWebpCtx);
-#else
-   _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_WEBP, WEBP, gdImageWebpCtx);
-#endif
+   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_WEBP, GIF, gdImageWebpCtx);
 }
 /* }}} */
 #endif /* HAVE_GD_WEBP */
@@ -2875,11 +2864,7 @@
Output JPEG image to browser or file */
 PHP_FUNCTION(imagejpeg)
 {
-#ifdef USE_GD_IOCTX
-   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_JPG, JPEG, gdImageJpegCtx);
-#else
-   _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, 
JPEG, gdImageJpeg);
-#endif
+   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_JPG, GIF, gdImageJpegCtx);
 }
 /* }}} */
 #endif /* HAVE_GD_JPG */
@@ -2889,11 +2874,7 @@
Output WBMP image to browser or file */
 PHP_FUNCTION(imagewbmp)
 {
-#ifdef USE_GD_IOCTX
-   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_WBM, WBMP, gdImageWBMPCtx);
-#else
-   _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, 
WBMP, gdImageWBMP);
-#endif
+   _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_WBM, GIF, gdImageWBMPCtx);
 }
 /* }}} */
 #endif /* HAVE_GD_WBMP */

Modified: php/php-src/trunk/ext/gd/gd_ctx.c
===
--- php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 07:24:19 UTC (rev 307017)
+++ php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 09:22:58 UTC (rev 307018)
@@ -46,6 +46,33 @@
}
 }

+static void _php_image_stream_putc(struct gdIOCtx *ctx, int c)  {
+   char ch = (char) c;
+   php_stream * stream = (php_stream *)ctx-data;
+   TSRMLS_FETCH();
+   php_stream_write(stream, ch, 1);
+}
+
+static int _php_image_stream_putbuf(struct gdIOCtx *ctx, const void* buf, int 
l)
+{
+   php_stream * stream = (php_stream *)ctx-data;
+   TSRMLS_FETCH();
+   return php_stream_write(stream, (void *)buf, l);
+}
+
+static void _php_image_stream_ctxfree(struct gdIOCtx *ctx)
+{
+   TSRMLS_FETCH();
+
+   if(ctx-data) {
+   php_stream_close((php_stream *) ctx-data);
+   ctx-data = NULL;
+   }
+   if(ctx) {
+   efree(ctx);
+   }
+}
+
 /* {{{ _php_image_output_ctx */
 static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int 
image_type, char *tn, void (*func_p)())
 {
@@ -54,17 +81,17 @@
int file_len = 0;
long quality, basefilter;
gdImagePtr im;
-   FILE *fp = NULL;
int argc = ZEND_NUM_ARGS();
int q = -1, i;
int f = -1;
-   gdIOCtx *ctx;
+   gdIOCtx *ctx = NULL;
+   zval *to_zval = NULL;
+   php_stream *stream;

/* The third (quality) parameter for Wbmp stands for the threshold when 
called from image2wbmp().
 * The third (quality) parameter for Wbmp and Xbm 

[PHP-CVS] svn: /php/php-src/trunk/ext/gd/ gd.c

2011-01-03 Thread Pierre Joye
pajoye   Mon, 03 Jan 2011 09:33:27 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307019

Log:
- kill c++ comment

Changed paths:
U   php/php-src/trunk/ext/gd/gd.c

Modified: php/php-src/trunk/ext/gd/gd.c
===
--- php/php-src/trunk/ext/gd/gd.c   2011-01-03 09:22:58 UTC (rev 307018)
+++ php/php-src/trunk/ext/gd/gd.c   2011-01-03 09:33:27 UTC (rev 307019)
@@ -2821,7 +2821,6 @@
 #if HAVE_GD_BUNDLED
 PHP_FUNCTION(imagexbm)
 {
-// _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_XBM, XBM, gdImageXbmCtx);
_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, 
PHP_GDIMG_TYPE_XBM, GIF, gdImageXbmCtx);
 }
 #endif

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-CVS] svn: /php/php-src/trunk/ext/gd/ gd_ctx.c

2011-01-03 Thread Pierre Joye
pajoye   Mon, 03 Jan 2011 15:35:01 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307029

Log:
- fix crash when argc  1 and to_zval is NULL (thx tony for the headup)

Changed paths:
U   php/php-src/trunk/ext/gd/gd_ctx.c

Modified: php/php-src/trunk/ext/gd/gd_ctx.c
===
--- php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 14:39:48 UTC (rev 307028)
+++ php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 15:35:01 UTC (rev 307029)
@@ -118,7 +118,7 @@
}
}

-   if (argc  1) {
+   if (argc  1  to_zval) {
if (Z_TYPE_P(to_zval) == IS_RESOURCE) {
php_stream_from_zval_no_verify(stream, to_zval);
if (stream == NULL) {

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-CVS] svn: /php/php-src/trunk/ext/gd/ gd_ctx.c

2011-01-03 Thread Pierre Joye
pajoye   Mon, 03 Jan 2011 15:36:39 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307030

Log:
- slightly cleaner

Changed paths:
U   php/php-src/trunk/ext/gd/gd_ctx.c

Modified: php/php-src/trunk/ext/gd/gd_ctx.c
===
--- php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 15:35:01 UTC (rev 307029)
+++ php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 15:36:39 UTC (rev 307030)
@@ -118,7 +118,7 @@
}
}

-   if (argc  1  to_zval) {
+   if (argc  1  to_zval != NULL) {
if (Z_TYPE_P(to_zval) == IS_RESOURCE) {
php_stream_from_zval_no_verify(stream, to_zval);
if (stream == NULL) {

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-CVS] svn: /php/php-src/ branches/PHP_5_3/ext/sqlite3/sqlite3.c trunk/ext/sqlite3/sqlite3.c

2011-01-03 Thread Scott MacVicar
scottmac Mon, 03 Jan 2011 19:15:36 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307037

Log:
Fix error with initialisation flag being set too early. If encryption is 
enabled and fails to decrypt a crash can occur.

Also fix a WS error.

Changed paths:
U   php/php-src/branches/PHP_5_3/ext/sqlite3/sqlite3.c
U   php/php-src/trunk/ext/sqlite3/sqlite3.c

Modified: php/php-src/branches/PHP_5_3/ext/sqlite3/sqlite3.c
===
--- php/php-src/branches/PHP_5_3/ext/sqlite3/sqlite3.c  2011-01-03 18:47:46 UTC 
(rev 307036)
+++ php/php-src/branches/PHP_5_3/ext/sqlite3/sqlite3.c  2011-01-03 19:15:36 UTC 
(rev 307037)
@@ -40,7 +40,7 @@
 static PHP_GINIT_FUNCTION(sqlite3);
 static int php_sqlite3_authorizer(void *autharg, int access_type, const char 
*arg3, const char *arg4, const char *arg5, const char *arg6);
 static void sqlite3_param_dtor(void *data);
-static int php_sqlite3_compare_stmt_zval_free( php_sqlite3_free_list 
**free_list, zval *statement );
+static int php_sqlite3_compare_stmt_zval_free(php_sqlite3_free_list 
**free_list, zval *statement);

 /* {{{ Error Handler
 */
@@ -152,8 +152,6 @@
return;
}

-   db_obj-initialised = 1;
-
 #if SQLITE_HAS_CODEC
if (encryption_key_len  0) {
if (sqlite3_key(db_obj-db, encryption_key, encryption_key_len) 
!= SQLITE_OK) {
@@ -163,6 +161,8 @@
}
 #endif

+   db_obj-initialised = 1;
+
 #if PHP_API_VERSION  20100412
if (PG(safe_mode) || (PG(open_basedir)  *PG(open_basedir))) {
 #else

Modified: php/php-src/trunk/ext/sqlite3/sqlite3.c
===
--- php/php-src/trunk/ext/sqlite3/sqlite3.c 2011-01-03 18:47:46 UTC (rev 
307036)
+++ php/php-src/trunk/ext/sqlite3/sqlite3.c 2011-01-03 19:15:36 UTC (rev 
307037)
@@ -40,7 +40,7 @@
 static PHP_GINIT_FUNCTION(sqlite3);
 static int php_sqlite3_authorizer(void *autharg, int access_type, const char 
*arg3, const char *arg4, const char *arg5, const char *arg6);
 static void sqlite3_param_dtor(void *data);
-static int php_sqlite3_compare_stmt_zval_free( php_sqlite3_free_list 
**free_list, zval *statement );
+static int php_sqlite3_compare_stmt_zval_free(php_sqlite3_free_list 
**free_list, zval *statement);

 /* {{{ Error Handler
 */
@@ -149,8 +149,6 @@
return;
}

-   db_obj-initialised = 1;
-
 #if SQLITE_HAS_CODEC
if (encryption_key_len  0) {
if (sqlite3_key(db_obj-db, encryption_key, encryption_key_len) 
!= SQLITE_OK) {
@@ -160,6 +158,8 @@
}
 #endif

+   db_obj-initialised = 1;
+
 #if PHP_API_VERSION  20100412
if (PG(safe_mode) || (PG(open_basedir)  *PG(open_basedir))) {
 #else

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-CVS] svn: /php/php-src/ branches/PHP_5_3/ext/date/lib/timelib_structs.h branches/PHP_5_3/ext/date/lib/unixtime2tm.c trunk/ext/date/lib/timelib_structs.h trunk/ext/date/lib/unixtime2tm.c

2011-01-03 Thread Scott MacVicar
scottmac Mon, 03 Jan 2011 19:24:04 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307038

Log:
Change DEBUG() to TIMELIB_DEBUG(), there are potential conflicts with other 
libraries that also use this.

Changed paths:
U   php/php-src/branches/PHP_5_3/ext/date/lib/timelib_structs.h
U   php/php-src/branches/PHP_5_3/ext/date/lib/unixtime2tm.c
U   php/php-src/trunk/ext/date/lib/timelib_structs.h
U   php/php-src/trunk/ext/date/lib/unixtime2tm.c

Modified: php/php-src/branches/PHP_5_3/ext/date/lib/timelib_structs.h
===
--- php/php-src/branches/PHP_5_3/ext/date/lib/timelib_structs.h 2011-01-03 
19:15:36 UTC (rev 307037)
+++ php/php-src/branches/PHP_5_3/ext/date/lib/timelib_structs.h 2011-01-03 
19:24:04 UTC (rev 307038)
@@ -218,6 +218,6 @@

 #define timelib_is_leap(y) ((y) % 4 == 0  ((y) % 100 != 0 || (y) % 400 == 0))

-#define DEBUG(s)  if (0) { s }
+#define TIMELIB_DEBUG(s)  if (0) { s }

 #endif

Modified: php/php-src/branches/PHP_5_3/ext/date/lib/unixtime2tm.c
===
--- php/php-src/branches/PHP_5_3/ext/date/lib/unixtime2tm.c 2011-01-03 
19:15:36 UTC (rev 307037)
+++ php/php-src/branches/PHP_5_3/ext/date/lib/unixtime2tm.c 2011-01-03 
19:24:04 UTC (rev 307038)
@@ -51,7 +51,7 @@
days++;
remainder -= SECS_PER_DAY;
}
-   DEBUG(printf(days=%lld, rem=%lld\n, days, remainder););
+   TIMELIB_DEBUG(printf(days=%lld, rem=%lld\n, days, remainder););

if (ts = 0) {
tmp_days = days + 1;
@@ -78,11 +78,11 @@
while (tmp_days = 0) {
if (tmp_days  -1460970) {
cur_year -= 4000;
-   DEBUG(printf(tmp_days=%lld, year=%lld\n, 
tmp_days, cur_year););
+   TIMELIB_DEBUG(printf(tmp_days=%lld, 
year=%lld\n, tmp_days, cur_year););
tmp_days += 1460970;
} else {
cur_year--;
-   DEBUG(printf(tmp_days=%lld, year=%lld\n, 
tmp_days, cur_year););
+   TIMELIB_DEBUG(printf(tmp_days=%lld, 
year=%lld\n, tmp_days, cur_year););
if (timelib_is_leap(cur_year)) {
tmp_days += DAYS_PER_LYEAR;
} else {
@@ -92,7 +92,7 @@
}
remainder += SECS_PER_DAY;
}
-   DEBUG(printf(tmp_days=%lld, year=%lld\n, tmp_days, cur_year););
+   TIMELIB_DEBUG(printf(tmp_days=%lld, year=%lld\n, tmp_days, 
cur_year););

months = timelib_is_leap(cur_year) ? month_tab_leap : month_tab;
if (timelib_is_leap(cur_year)  cur_year  1970) {
@@ -100,19 +100,19 @@
}
i = 11;
while (i  0) {
-   DEBUG(printf(month=%lld (%d)\n, i, months[i]););
+   TIMELIB_DEBUG(printf(month=%lld (%d)\n, i, months[i]););
if (tmp_days  months[i]) {
break;
}
i--;
}
-   DEBUG(printf(A: ts=%lld, year=%lld, month=%lld, day=%lld,, ts, 
cur_year, i + 1, tmp_days - months[i]););
+   TIMELIB_DEBUG(printf(A: ts=%lld, year=%lld, month=%lld, day=%lld,, 
ts, cur_year, i + 1, tmp_days - months[i]););

/* That was the date, now we do the tme */
hours = remainder / 3600;
minutes = (remainder - hours * 3600) / 60;
seconds = remainder % 60;
-   DEBUG(printf( hour=%lld, minute=%lld, second=%lld\n, hours, minutes, 
seconds););
+   TIMELIB_DEBUG(printf( hour=%lld, minute=%lld, second=%lld\n, hours, 
minutes, seconds););

tm-y = cur_year;
tm-m = i + 1;
@@ -240,18 +240,18 @@
 {
if (localtime) {
/* Converting from GMT time to local time */
-   DEBUG(printf(Converting from GMT time to local time\n););
+   TIMELIB_DEBUG(printf(Converting from GMT time to local 
time\n););

/* Check if TZ is set */
if (!t-tz_info) {
-   DEBUG(printf(E: No timezone configured, can't switch 
to local time\n););
+   TIMELIB_DEBUG(printf(E: No timezone configured, can't 
switch to local time\n););
return -1;
}

timelib_unixtime2local(t, t-sse);
} else {
/* Converting from local time to GMT time */
-   DEBUG(printf(Converting from local time to GMT time\n););
+   TIMELIB_DEBUG(printf(Converting from local time to GMT 
time\n););

timelib_unixtime2gmt(t, t-sse);
}

Modified: php/php-src/trunk/ext/date/lib/timelib_structs.h
===
--- 

[PHP-CVS] svn: /php/php-src/trunk/ext/gd/ gd_ctx.c

2011-01-03 Thread Pierre Joye
pajoye   Mon, 03 Jan 2011 20:38:21 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307039

Log:
- useless commented code

Changed paths:
U   php/php-src/trunk/ext/gd/gd_ctx.c

Modified: php/php-src/trunk/ext/gd/gd_ctx.c
===
--- php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 19:24:04 UTC (rev 307038)
+++ php/php-src/trunk/ext/gd/gd_ctx.c   2011-01-03 20:38:21 UTC (rev 307039)
@@ -103,7 +103,6 @@
 * PHP_GDIMG_TYPE_WBM
 * PHP_GDIMG_TYPE_WEBP
 * */
-   //if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 
r|s!ll, imgind, file, file_len, quality, basefilter) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, r|z/!ll, 
imgind, to_zval, quality, basefilter) == FAILURE) {
return;
}

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-CVS] svn: /php/php-src/ branches/PHP_5_3/win32/build/confutils.js trunk/win32/build/confutils.js

2011-01-03 Thread Kalle Sommer Nielsen
kalleMon, 03 Jan 2011 23:08:47 +

Revision: http://svn.php.net/viewvc?view=revisionrevision=307044

Log:
Fixed linking of extensions that would use a static .lib file (libname_a.lib 
rather than libname.lib)

# This fixes `configure --with-mcrypt=shared' to properly find and
# link against libmcrypt.lib rather than libmcrypt_a.lib

Changed paths:
U   php/php-src/branches/PHP_5_3/win32/build/confutils.js
U   php/php-src/trunk/win32/build/confutils.js

Modified: php/php-src/branches/PHP_5_3/win32/build/confutils.js
===
--- php/php-src/branches/PHP_5_3/win32/build/confutils.js   2011-01-03 
23:08:22 UTC (rev 307043)
+++ php/php-src/branches/PHP_5_3/win32/build/confutils.js   2011-01-03 
23:08:47 UTC (rev 307044)
@@ -648,6 +648,9 @@
// Expand path to include general dirs
path_to_check += ; + php_usual_lib_suspects;

+   // For static libs
+   eval('var static_lib = !PHP_' + common_name.toUpperCase() + '_SHARED;');
+
// It is common practice to put libs under one of these dir names
var subdirs = new Array(PHP_DEBUG == yes ? Debug : (PHP_DEBUG_PACK 
== yes?Release_Dbg:Release), lib, libs, libexec);

@@ -663,6 +666,14 @@
name = name.replace(rExp,_debug.lib);
libnames.unshift(name);
}
+   } else if (!static_lib) {
+   var length = libnames.length;
+   for (var i = 0; i  length; i++) {
+   var name = new String(libnames[i]);
+   rExp = /_a.lib$/i;
+   name = name.replace(rExp,.lib);
+   libnames.unshift(name);
+   }
}

var i, j, k, libname;

Modified: php/php-src/trunk/win32/build/confutils.js
===
--- php/php-src/trunk/win32/build/confutils.js  2011-01-03 23:08:22 UTC (rev 
307043)
+++ php/php-src/trunk/win32/build/confutils.js  2011-01-03 23:08:47 UTC (rev 
307044)
@@ -648,6 +648,9 @@
// Expand path to include general dirs
path_to_check += ; + php_usual_lib_suspects;

+   // For static libs
+   eval('var static_lib = !PHP_' + common_name.toUpperCase() + '_SHARED;');
+
// It is common practice to put libs under one of these dir names
var subdirs = new Array(PHP_DEBUG == yes ? Debug : (PHP_DEBUG_PACK 
== yes?Release_Dbg:Release), lib, libs, libexec);

@@ -663,6 +666,14 @@
name = name.replace(rExp,_debug.lib);
libnames.unshift(name);
}
+   } else if (!static_lib) {
+   var length = libnames.length;
+   for (var i = 0; i  length; i++) {
+   var name = new String(libnames[i]);
+   rExp = /_a.lib$/i;
+   name = name.replace(rExp,.lib);
+   libnames.unshift(name);
+   }
}

var i, j, k, libname;

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php