diff options
author | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2006-01-02 01:06:06 +0000 |
---|---|---|
committer | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2006-01-02 01:06:06 +0000 |
commit | 83f3c4114164617f48f3b013027f9079ddc2675c (patch) | |
tree | 3fc5ba313a14992eb3683e2a2e46c095fc7a8f7f | |
parent | 5c2efb82b74874e5f7220cb1a00479c009d9221b (diff) | |
download | ampache-83f3c4114164617f48f3b013027f9079ddc2675c.tar.gz ampache-83f3c4114164617f48f3b013027f9079ddc2675c.tar.bz2 ampache-83f3c4114164617f48f3b013027f9079ddc2675c.zip |
updated registration mojo thx pb1dft also some fluf updates
66 files changed, 2124 insertions, 270 deletions
diff --git a/activate.php b/activate.php new file mode 100644 index 00000000..4aeb00da --- /dev/null +++ b/activate.php @@ -0,0 +1,49 @@ +<?php +/* + + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +$no_session = true; +require_once( "modules/init.php" ); +if(conf('demo_mode')) { + access_denied(); +} + +// Access Control +echo "<html><head>"; +show_template('style'); +echo "<head><body>"; + + +$username = $_GET['u']; +$validation = $_GET['act_key']; +$user = new User($username); +$val1 = $GLOBALS['user']->get_user_validation($username,$validation); +if (!$val1){ + $GLOBALS['error']->add_error('no_such_user',_("No user with this name registered")); + $GLOBALS['error']->print_error('no_such_user'); + echo "</body></html>"; + break; + } +$activate = $GLOBALS['user']->activate_user($username); +show_confirmation('User activated','This User ID is activated and can be used','/login.php'); +echo "</body></html>"; + +?> diff --git a/albumart.php b/albumart.php index fd7c7f41..7d29decb 100644 --- a/albumart.php +++ b/albumart.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/artists.php b/artists.php index 4ff8fa22..a46396ee 100644 --- a/artists.php +++ b/artists.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All Rights Reserved This program is free software; you can redistribute it and/or diff --git a/config/ampache.cfg.php.dist b/config/ampache.cfg.php.dist index 77a134d3..2e832621 100644 --- a/config/ampache.cfg.php.dist +++ b/config/ampache.cfg.php.dist @@ -122,9 +122,21 @@ require_session = "true" # This setting turns on/off public registration. It is # recommended you leave this off, as it will allow anyone to # sign up for an account on your server. +# REMEMBER: don't forget to set the mail from address futher down in the config. # DEFAULT: false #allow_public_registration = "false" +# This setting defines the mail domain your in. +# It tries to deliver a test mail before the user can register and uses +# the from address info@"domain.tld". No mail is send from this address it's +# only used to test the existense of a mailbox before accepting user registration. +# DEFAULT: domain.tld +#mail_domain = "domain.tld" + +# This settting will be used as mail from address. +# You need to change this when you activate public_registration. +mail_from = "info@domain.tld" + # This setting will allow all registrants to be auto-approved # as a user. By default, they will be added as a guest and # must be "promoted" by the admin. diff --git a/docs/CHANGELOG b/docs/CHANGELOG index da0bbc49..bd78f752 100755 --- a/docs/CHANGELOG +++ b/docs/CHANGELOG @@ -4,6 +4,8 @@ -------------------------------------------------------------------------- v.3.3.2-Beta1 + - Updated Registration code (Thx pb1dft) + - Updated GetId3() Library to v.1.7.5 - Updated SQL file - Fixed Install script so it throws errors and is now able to if specified create the database user for you @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 @@ -1,8 +1,7 @@ <?php - /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/install.php b/install.php index c2b46a7d..49090bf9 100644 --- a/install.php +++ b/install.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 ampache.org + Copyright (c) 2001 - 2006 ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/artist.lib.php b/lib/artist.lib.php index aa89e482..bfd956b6 100644 --- a/lib/artist.lib.php +++ b/lib/artist.lib.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/batch.lib.php b/lib/batch.lib.php index 5cb8494f..af4ed80a 100644 --- a/lib/batch.lib.php +++ b/lib/batch.lib.php @@ -1,19 +1,22 @@ <?php /* -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/lib/class/access.class.php b/lib/class/access.class.php index 85fc3a81..8a0ad168 100644 --- a/lib/class/access.class.php +++ b/lib/class/access.class.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/class/album.class.php b/lib/class/album.class.php index 5b56d90a..08da4c4e 100644 --- a/lib/class/album.class.php +++ b/lib/class/album.class.php @@ -1,7 +1,8 @@ <?php /* - Copyright (c) 2004 - Ampache.org + + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/lib/class/artist.class.php b/lib/class/artist.class.php index 5f9267b3..961b5991 100644 --- a/lib/class/artist.class.php +++ b/lib/class/artist.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2004 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/class/catalog.class.php b/lib/class/catalog.class.php index 2265afba..dcbf074e 100644 --- a/lib/class/catalog.class.php +++ b/lib/class/catalog.class.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/class/error.class.php b/lib/class/error.class.php index 5515e41c..b3e74ba5 100644 --- a/lib/class/error.class.php +++ b/lib/class/error.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/class/genre.class.php b/lib/class/genre.class.php index dd664c5b..5d4e13d1 100644 --- a/lib/class/genre.class.php +++ b/lib/class/genre.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright 2001 - 2005 Ampache.org + Copyright 2001 - 2006 Ampache.org All Rights Reserved This program is free software; you can redistribute it and/or diff --git a/lib/class/playlist.class.php b/lib/class/playlist.class.php index 765a2219..279134ee 100644 --- a/lib/class/playlist.class.php +++ b/lib/class/playlist.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/class/rating.class.php b/lib/class/rating.class.php index 06344e1c..f9dd0794 100644 --- a/lib/class/rating.class.php +++ b/lib/class/rating.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/class/song.class.php b/lib/class/song.class.php index d857e68a..e0f7dd36 100644 --- a/lib/class/song.class.php +++ b/lib/class/song.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2004 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/class/stream.class.php b/lib/class/stream.class.php index 16a7c722..9bf5b7f1 100644 --- a/lib/class/stream.class.php +++ b/lib/class/stream.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/class/update.class.php b/lib/class/update.class.php index d6890465..4977135a 100644 --- a/lib/class/update.class.php +++ b/lib/class/update.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/class/user.class.php b/lib/class/user.class.php index 8442da90..83b473a3 100644 --- a/lib/class/user.class.php +++ b/lib/class/user.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or @@ -36,6 +36,8 @@ class User { var $offset_limit=25; var $email; var $last_seen; + var $reg_date; + var $validation; function User($username=0) { @@ -52,6 +54,8 @@ class User { $this->offset_limit = $info->offset_limit; $this->email = $info->email; $this->last_seen = $info->last_seen; + $this->reg_date = $info->reg_date; + $this->validation = $info->validation; $this->set_preferences(); // Make sure the Full name is always filled @@ -476,10 +480,9 @@ class User { $username = sql_escape($username); $fullname = sql_escape($fullname); $email = sql_escape($email); - /* Now Insert this new user */ - $sql = "INSERT INTO user (username, fullname, email, password, access) VALUES" . - " ('$username','$fullname','$email',PASSWORD('$password'),'$access')"; + $sql = "INSERT INTO user (username, fullname, email, password, access, reg_date) VALUES" . + " ('$username','$fullname','$email',PASSWORD('$password'),'$access', unix_timestamp())"; $db_results = mysql_query($sql, dbh()); if (!$db_results) { return false; } @@ -737,9 +740,31 @@ class User { @description calcs difference between now and last_seen if less than delay, we consider them still online */ + function is_online( $delay = 1200 ) { return time() - $this->last_seen <= $delay; } + /*! + @function get_user_validation + @check if user exists before activation can be done. + */ + function get_user_validation($username,$validation){ + $sql = "SELECT validation FROM user where username='$username'"; + $db_results = mysql_query($sql, dbh()); + $row = mysql_fetch_array($db_results); + $val = $row[validation]; + return $val; + } // get_user_validation + + /*! + @function activate_user + @activates the user from public_registration + */ + function activate_user($username) { + $sql = "UPDATE user SET disabled='0' WHERE username='$username'"; + $db_results = mysql_query($sql, dbh()); + } // activate_user } //end class + ?> diff --git a/lib/class/view.class.php b/lib/class/view.class.php index 112148ad..afc81b22 100644 --- a/lib/class/view.class.php +++ b/lib/class/view.class.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2004 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/debug.php b/lib/debug.php index c554daf7..8d24d54d 100644 --- a/lib/debug.php +++ b/lib/debug.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2004 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/duplicates.php b/lib/duplicates.php index 93e082d9..75ca2a22 100644 --- a/lib/duplicates.php +++ b/lib/duplicates.php @@ -1,4 +1,26 @@ <?php +/* + + Copyright (c) 2001 - 2006 Ampache.org + All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + + /*! @header Contains the functions for handling duplicate songs */ diff --git a/lib/flag.php b/lib/flag.php index da371793..5e16faeb 100644 --- a/lib/flag.php +++ b/lib/flag.php @@ -1,10 +1,9 @@ <?php /* - Copyright (c) 2004 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/general.lib.php b/lib/general.lib.php index cc49d7be..983b4c12 100644 --- a/lib/general.lib.php +++ b/lib/general.lib.php @@ -1,5 +1,27 @@ <?php /* + + Copyright (c) 2001 - 2006 Ampache.org + All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + + +/* @header General Library This is the general library that contains misc functions that doesn't have a home elsewhere diff --git a/lib/gettext.php b/lib/gettext.php index 064173d6..602f3365 100644 --- a/lib/gettext.php +++ b/lib/gettext.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/install.php b/lib/install.php index c3c1c8b4..3ca0fb79 100644 --- a/lib/install.php +++ b/lib/install.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/log.lib.php b/lib/log.lib.php index e196a73f..0f9e6a99 100644 --- a/lib/log.lib.php +++ b/lib/log.lib.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/mpd.php b/lib/mpd.php index efbbda6e..26053267 100644 --- a/lib/mpd.php +++ b/lib/mpd.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/preferences.php b/lib/preferences.php index dea96529..c33980f3 100644 --- a/lib/preferences.php +++ b/lib/preferences.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/rss.php b/lib/rss.php index 4fc849d2..eefb9ad1 100644 --- a/lib/rss.php +++ b/lib/rss.php @@ -1,7 +1,7 @@ <?php /* - Copyright 2001 - 2005 Ampache.org + Copyright 2001 - 2006 Ampache.org All Rights Reserved This program is free software; you can redistribute it and/or diff --git a/lib/search.php b/lib/search.php index 8484c71f..818c91d2 100644 --- a/lib/search.php +++ b/lib/search.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2004 ampache.org + Copyright (c) 2001 - 2006 ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/lib/song.php b/lib/song.php index 7c9a3282..ba453d5c 100644 --- a/lib/song.php +++ b/lib/song.php @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 diff --git a/lib/stream.lib.php b/lib/stream.lib.php index 57be2fe3..f1f0a366 100644 --- a/lib/stream.lib.php +++ b/lib/stream.lib.php @@ -1,7 +1,7 @@ <?php /* - Copyright 2001 - 2005 Ampache.org + Copyright 2001 - 2006 Ampache.org All Rights Reserved This program is free software; you can redistribute it and/or diff --git a/lib/themes.php b/lib/themes.php index 1c67c5a7..aac16330 100644 --- a/lib/themes.php +++ b/lib/themes.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All Rights Reserved This program is free software; you can redistribute it and/or diff --git a/lib/ui.lib.php b/lib/ui.lib.php index 77693a05..e1144abb 100644 --- a/lib/ui.lib.php +++ b/lib/ui.lib.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or @@ -1132,6 +1132,7 @@ function new_user($username, $fullname, $email, $password) { $username = sql_escape($username); $fullname = sql_escape($fullname); $email = sql_escape($email); + $validation = str_rand(20); $access = '5'; if(conf('auto_user')){ $access='25'; @@ -1146,11 +1147,12 @@ function new_user($username, $fullname, $email, $password) { /* Uhh let's not auto-pass through in this fashion FIXME */ else { /* Apparently it's a new user, now insert the user into the database*/ - $sql = "INSERT INTO user (username, fullname, email, password, access) VALUES" . - " ('$username','$fullname','$email',PASSWORD('$password'),'$access')"; + $sql = "INSERT INTO user (username, fullname, email, password, access, disabled, reg_date, validation) VALUES" . + " ('$username','$fullname','$email',PASSWORD('$password'),'$access', '1', unix_timestamp(), '$validation')"; $db_results = mysql_query($sql, dbh()); show_template('style'); - show_confirmation('Registration Complete','You have registered succesfully','/login.php'); + show_confirmation('Registration Complete','Your account has been created. However, this forum requires account activation. An activation key has been sent to the e-mail address you provided. Please check your e-mail for further information','/login.php'); + send_confirmation($username, $fullname, $email, $password, $validation); } return true; @@ -1192,6 +1194,60 @@ function good_email($email) { return true; } //good_email +/** + * str_rand + * + * + */ +function str_rand($length = 8, $seeds = 'abcdefghijklmnopqrstuvwxyz0123456789'){ + $str = ''; + $seeds_count = strlen($seeds); + + // Seed + list($usec, $sec) = explode(' ', microtime()); + $seed = (float) $sec + ((float) $usec * 100000); + mt_srand($seed); + + // Generate + for ($i = 0; $length > $i; $i++) { + $str .= $seeds{mt_rand(0, $seeds_count - 1)}; + } + + return $str; +} //str_rand + +/** + * send_confirmation + * + * + */ +function send_confirmation($username, $fullname, $email, $password, $validation) { + +$title = conf('site_title'); +$from = "From: Ampache <".conf('mail_from').">"; +$body = "Welcome to $title + +Please keep this email for your records. Your account information is as follows: + +---------------------------- +Username: $username +Password: $password +---------------------------- + +Your account is currently inactive. You cannot use it until you visit the following link: +" +. conf('web_path'). "/activate.php?mode=activate&u=$username&act_key=$validation + +Please do not forget your password as it has been encrypted in our database and we cannot retrieve it for you. However, should you forget your password you can request a new one which will be activated in the same way as this account. + +Thank you for registering."; + + +mail($email, "Welcome to $title" , $body, $from); + +} //send_confirmation + + ?> diff --git a/lib/upload.php b/lib/upload.php index 97c60118..a24c55c5 100644 --- a/lib/upload.php +++ b/lib/upload.php @@ -1,5 +1,8 @@ <?php /* + + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/lib/xmlrpc.php b/lib/xmlrpc.php index e1408ac8..cd6c3e70 100644 --- a/lib/xmlrpc.php +++ b/lib/xmlrpc.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/localplay.php b/localplay.php index 9dda39cc..4e9b66d0 100644 --- a/localplay.php +++ b/localplay.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2004 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or @@ -1,6 +1,9 @@ <?php /* + Copyright (c) 2001 - 2006 Ampache.org + All Rights Reserved + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 @@ -1,16 +1,32 @@ <?php +/* + + Copyright (c) 2001 - 2006 Ampache.org + All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/** + * Logout + * This is the logout page, it kills any cookies you have in your browser kills + * your session in the database and then redirects you to the login page + */ + require_once("modules/init.php"); // To end a legitimate session, just call logout. setcookie("amp_longsess","",null); logout(); ?> - -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-transitional.dtd"> -<html> -<head> -<title>Sample logout page</title> -</head> -<body> -Congrats, you are logged out. -<br /><a href="./login.php">login</a> -</body></html> diff --git a/modules/captcha/COLLEGE.ttf b/modules/captcha/COLLEGE.ttf Binary files differnew file mode 100644 index 00000000..400fe5ce --- /dev/null +++ b/modules/captcha/COLLEGE.ttf diff --git a/modules/captcha/captcha.php b/modules/captcha/captcha.php new file mode 100644 index 00000000..039d1907 --- /dev/null +++ b/modules/captcha/captcha.php @@ -0,0 +1,303 @@ +<?php +/* + Does emit a CAPTCHA graphic and form fields, which allows to tell real + people from bots. + Though a textual description is generated as well, this sort of access + restriction will knock out visually impaired users, and frustrate all + others anyhow. Therefore this should only be used as last resort for + defending against spambots. Because of the readable text and the used + colorspaces this is a weak implementation, not completely OCR-secure. + + captcha::form() will return a html string to be inserted into textarea/ + [save] <forms> and alike. User input is veryfied with captcha::check(). + You should leave the sample COLLEGE.ttf next to this script, else you + have to define the _FONT_DIR constant correctly. Use only one type. + + Includes a sluggish workaround for Internet Explorer; but this script + must reside in a www-accessible directory then. + Public Domain, available via http://freshmeat.net/p/captchaphp +*/ + + +#-- config +define("EWIKI_FONT_DIR", dirname(__FILE__)); // which fonts to use +define("CAPTCHA_INVERSE", 0); // white or black(=1) +define("CAPTCHA_TIMEOUT", 5000); // in seconds (=max 4 hours) + + +/* static - (you could instantiate it, but...) */ +class captcha { + + + /* gets parameter from $_REQUEST[] array (POST vars) and so can + verify input, @returns boolean + */ + function check() { + if (($hash = $_REQUEST["captcha_hash"]) + and ($pw = trim($_REQUEST["captcha_input"]))) { + return((captcha::hash($pw)==$hash) || (captcha::hash($pw,-1)==$hash)); + } + } + + + /* yields <input> fields html string (no complete form), with captcha + image already embedded as data:-URI + */ + function form($title="→ retype that here", $more="<small><br>Enter the correct letters and numbers from the image into the text box. <br>This small test serves as access restriction against malicious bots. <br>Simply reload the page if this graphic is too hard to read.</small>") { + $pw = captcha::mkpass(); + $hash = captcha::hash($pw); +// $maxsize = (strpos("MSIE", $_SERVER["HTTP_USER_AGENT"]) ? 1000 : 6000); + $maxsize = 100; + @header("Vary: User-Agent"); + $img = "data:image/jpeg;base64," + . base64_encode(captcha::image($pw, 200, 60, CAPTCHA_INVERSE, $maxsize)); + $alt = htmlentities(captcha::textual_riddle($pw)); + $test = substr($img,22); + $html = + '<table border="0" summary="captcha input"><tr>' + . '<td><img name="captcha_image" id="captcha_image" src="'.$img. '" height="60" width="200" alt="'.$alt. '" /></td>' + . '<td>'.$title. '<br/><input name="captcha_hash" type="hidden" value="'.$hash. '" />' + . '<font color="red">*</font><input name="captcha_input" type="text" size="7" maxlength="16" style="height:23px; font-size:16px; font-weight:450;" />' + . '</td><td>'.$more.'</td>' + . '</tr></table>'; + +// '<table border="0" summary="captcha input"><tr>' +// '<img name="captcha_image" id="captcha_image" src="'.$img. '" height="60" width="200" alt="'.$alt. '" /></td>' +// . '<td><img name="captcha_image" id="captcha_image" src="'.$img.'" height="60" width="200" alt="'.$alt. '" /></td>' +// . '<td>'.$title. '<br/><input name="captcha_hash" type="hidden" value="'.$hash. '" />' +// ''.$title. '<br/><input name="captcha_hash" type="hidden" value="'.$hash. '" />' +// . '<input name="captcha_input" type="text" size="7" maxlength="16" style="height:23px; font-size:16px; font-weight:450;" />' +// . '<td width="80%">'.$more.'</td>' +// . '</tr></table>'; + + #-- js/html fix if ("MSIE") + { + $base = "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]/ampache/captcha.php"; +// $base = "http://10.60.60.16/ampache/captcha.php"; +// . substr(realpath(__FILE__), strlen($_SERVER["DOCUMENT_ROOT"])); + $html .= <<<END +<script language="Javascript"><!-- +if (/Microsoft/.test(navigator.appName)) { +// var msg= "You are using IE Please download firefox in order to register. http://www.mozilla.org/products/firefox"; +// alert(msg); + var img = document.captcha_image; + img.src = "$base?_ddu=$test"; + //alert (img.src); + } +--></script> +END; + } + $html = "<div class=\"captcha\">$html</div>"; + return($html); + } +/*<script language="Javascript"><!-- +if (/Microsoft/.test(navigator.appName)) { + var img = document.captcha_image; + img.src = "$base?_ddu=" + img.src.substr(23); + } +--></script>/* + + + /* generates alternative (non-graphic), human-understandable + representation of the passphrase + */ + function textual_riddle($phrase) { + $symbols0 = '"\'-/_:'; + $symbols1 = array("\n,", "\n;", ";", "\n&", "\n-", ",", ",", "\nand then", "\nfollowed by", "\nand", "\nand not a\n\"".chr(65+rand(0,26))."\",\nbut"); + $s = "Guess the letters and numbers\n(passphrase riddle)\n--\n"; + for ($p=0; $p<strlen($phrase); $p++) { + $c = $phrase[$p]; + $add = ""; + #-- asis + if (!rand(0,3)) { + $i = $symbols0[rand(0,strlen($symbols0)-1)]; + $add = "$i$c$i"; + } + #-- letter + elseif ($c >= 'A') { + $type = ($c >= 'a' ? "small " : ""); + do { + $n = rand(-3,3); + $c2 = chr((ord($c) & 0x5F) + $n); + } + while (($c2 < 'A') || ($c2 > 'Z')); + if ($n < 0) { + $n = -$n; + $add .= "$type'$c2' +$n letters"; + } + else { + $add .= "$n chars before $type$c2"; + } + } + #-- number + else { + $add = "???"; + $n = (int) $c; + do { + do { $x = rand(1, 10); } while (!$x); + $op = rand(0,11); + if ($op <= 2) { + $add = "($add * $x)"; $n *= $x; + } + elseif ($op == 3) { + $x = 2 * rand(1,2); + $add = "($add / $x)"; $n /= $x; + } + elseif ($sel % 2) { + $add = "($add + $x)"; $n += $x; + } + else { + $add = "($add - $x)"; $n -= $x; + } + } + while (rand(0,1)); + $add .= " = $n"; + } + $s .= "$add"; + $s .= $symbols1[rand(0,count($symbols1)-1)] . "\n"; + } + return($s); + } + + + /* returns jpeg file stream with unscannable letters encoded + in front of colorful disturbing background + */ + function image($phrase, $width=200, $height=60, $inverse=0, $maxsize=0xFFFFF) { + + #-- initialize in-memory image with gd library + srand(microtime()*21017); + $img = imagecreatetruecolor($width, $height); + $R = $inverse ? 0xFF : 0x00; + imagefilledrectangle($img, 0,0, $width,$height, captcha::random_color($img, 222^$R, 255^$R)); + $c1 = rand(150^$R, 185^$R); + $c2 = rand(195^$R, 230^$R); + + #-- configuration + $fonts = array( + // "COLLEGE.ttf", + ); + $fonts += glob(EWIKI_FONT_DIR."/*.ttf"); + + #-- encolour bg + $wd = 20; + $x = 0; + while ($x < $width) { + imagefilledrectangle($img, $x, 0, $x+=$wd, $height, captcha::random_color($img, 222^$R, 255^$R)); + $wd += max(10, rand(0, 20) - 10); + } + + #-- make interesting background I, lines + $wd = 4; + $w1 = 0; + $w2 = 0; + for ($x=0; $x<$width; $x+=(int)$wd) { + if ($x < $width) { // verical + imageline($img, $x+$w1, 0, $x+$w2, $height-1, captcha::random_color($img,$c1,$c2)); + } + if ($x < $height) { // horizontally ("y") + imageline($img, 0, $x-$w2, $width-1, $x-$w1, captcha::random_color($img,$c1,$c2)); + } + $wd += rand(0,8) - 4; + if ($wd < 1) { $wd = 2; } + $w1 += rand(0,8) - 4; + $w2 += rand(0,8) - 4; + if (($x > $height) && ($y > $height)) { + break; + } + } + + #-- more disturbing II, random letters + $limit = rand(30,90); + for ($n=0; $n<$limit; $n++) { + $letter = ""; + do { + $letter .= chr(rand(31,125)); // random symbol + } while (rand(0,1)); + $size = rand(5, $height/2); + $half = (int) ($size / 2); + $x = rand(-$half, $width+$half); + $y = rand(+$half, $height); + $rotation = rand(60, 300); + $c1 = captcha::random_color($img, 130^$R, 240^$R); + $font = $fonts[rand(0, count($fonts)-1)]; + imagettftext($img, $size, $rotation, $x, $y, $c1, $font, $letter); + } + + #-- add the real text to it + $len = strlen($phrase); + $w1 = 10; + $w2 = $width / ($len+1); + for ($p=0; $p<$len; $p++) { + $letter = $phrase[$p]; + $size = rand(18, $height/2.2); + $half = (int) $size / 2; + $rotation = rand(-33, 33); + $y = rand($size+3, $height-3); + $x = $w1 + $w2*$p; + $w1 += rand(-$width/90, $width/40); // @BUG: last char could be +30 pixel outside of image + $font = $fonts[rand(0, count($fonts)-1)]; + $r=rand(30,99); $g=rand(30,99); $b=rand(30,99); // two colors for shadow + $c1 = imagecolorallocate($img, $r*1^$R, $g*1^$R, $b*1^$R); + $c2 = imagecolorallocate($img, $r*2^$R, $g*2^$R, $b*2^$R); + imagettftext($img, $size, $rotation, $x+1, $y, $c2, $font, $letter); + imagettftext($img, $size, $rotation, $x, $y-1, $c1, $font, $letter); + } + + #-- let JFIF stream be generated +// $quality = 67; + $quality = 8; + $s = array(); + do { + ob_start(); ob_implicit_flush(0); + imagejpeg($img, "", (int)$quality); + $jpeg = ob_get_contents(); ob_end_clean(); + $size = strlen($jpeg); + $s_debug[] = ((int)($quality*10)/10) . "%=$size"; + $quality = $quality * ($maxsize/$size) * 0.93 - 1.7; // -($quality/7.222)* + } + while (($size > $maxsize) && ($quality >= 16)); + imagedestroy($img); +#print_r($s_debug); + return($jpeg); + } + + + /* helper code */ + function random_color($img, $a,$b) { + return imagecolorallocate($img, rand($a,$b), rand($a,$b), rand($a,$b)); + } + + + /* unreversable hash from passphrase, with time() slice encoded */ + function hash($text, $dtime=0) { + $text = strtolower($text); + $pfix = (int) (time() / CAPTCHA_TIMEOUT) + $dtime; + return md5("captcha::$pfix:$text::".__FILE__.":$_SERVER[SERVER_NAME]:80"); + } + + + /* makes string of random letters for embedding into image and for + encoding as hash, later verification + */ + function mkpass() { + $s = ""; + for ($n=0; $n<10; $n++) { + $s .= chr(rand(0, 255)); + } + $s = base64_encode($s); // base64-set, but filter out unwanted chars + $s = preg_replace("/[+\/=IG0ODQR]/i", "", $s); // (depends on YOUR font) + $s = substr($s, 0, rand(5,7)); + return($s); + } +} + + +#-- IE workaround +if (isset($_REQUEST["_ddu"])) { + header("Content-Type: image/jpeg"); + die(base64_decode(substr($_REQUEST["_ddu"], 0))); +} + + +?> diff --git a/modules/id3/getid3/getid3.php b/modules/id3/getid3/getid3.php index e87fcfb6..d0a8d479 100644 --- a/modules/id3/getid3/getid3.php +++ b/modules/id3/getid3/getid3.php @@ -10,7 +10,7 @@ ///////////////////////////////////////////////////////////////// // Defines -define('GETID3_VERSION', '1.7.4'); +define('GETID3_VERSION', '1.7.5-200512251515'); define('GETID3_FREAD_BUFFER_SIZE', 16384); // read buffer size in bytes @@ -111,26 +111,40 @@ class getID3 // ie for "C:/Program Files/Apache/" put "C:/PROGRA~1/APACHE/" // IMPORTANT: This path must include the trailing slash if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) { - $helperappsdir = GETID3_INCLUDEPATH.'..'.GETID3_OS_DIRSLASH.'helperapps'; // must not have any space in this path if (!is_dir($helperappsdir)) { + $this->startup_error .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'; + } elseif (strpos(realpath($helperappsdir), ' ') !== false) { + $DirPieces = explode(GETID3_OS_DIRSLASH, realpath($helperappsdir)); - foreach ($DirPieces as $key => $value) { - if ((strpos($value, '.') !== false) && (strpos($value, ' ') === false)) { - if (strpos($value, '.') > 8) { - $value = substr($value, 0, 6).'~1'; - } - } elseif ((strpos($value, ' ') !== false) || strlen($value) > 8) { - $value = substr($value, 0, 6).'~1'; - } - $DirPieces[$key] = strtoupper($value); - } - $this->startup_error .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary (on this server that would be something like "'.implode(GETID3_OS_DIRSLASH, $DirPieces).'" - NOTE: this may or may not be the actual 8.3 equivalent of "'.$helperappsdir.'", please double-check). You can run "dir /x" from the commandline to see the correct 8.3-style names. You need to edit the file "'.GETID3_INCLUDEPATH.'/getid3.php" around line '.(__LINE__ - 16); + $DirPieces8 = $DirPieces;
+
+ $CLIdir = $DirPieces[0].' && cd \\';
+ for ($i = 1; $i < count($DirPieces); $i++) {
+ if (strpos($DirPieces[$i], ' ') === false) {
+ $CLIdir .= ' && cd '.$DirPieces[$i];
+ } else {
+ ob_start();
+ system($CLIdir.' && dir /ad /x');
+ $subdirsraw = explode("\n", ob_get_contents());
+ ob_end_clean();
+ foreach ($subdirsraw as $line) {
+ if (eregi('^[0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [AP]M <DIR> ([^ ]{8}) '.preg_quote($DirPieces[$i]).'$', trim($line), $matches)) {
+ $CLIdir .= ' && cd '.$matches[1];
+ break;
+ }
+ }
+ $DirPieces8[$i] = $matches[1];
+ }
+ }
+ $helperappsdir = implode(GETID3_OS_DIRSLASH, $DirPieces8); + } define('GETID3_HELPERAPPSDIR', realpath($helperappsdir).GETID3_OS_DIRSLASH); + } } @@ -436,7 +450,7 @@ class getID3 'group' => 'audio', 'module' => 'ac3', 'mime_type' => 'audio/ac3', - ), + ), // AAC - audio - Advanced Audio Coding (AAC) - ADIF format 'adif' => array( @@ -446,7 +460,7 @@ class getID3 'option' => 'adif', 'mime_type' => 'application/octet-stream', 'fail_ape' => 'WARNING', - ), + ), // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3) @@ -457,7 +471,7 @@ class getID3 'option' => 'adts', 'mime_type' => 'application/octet-stream', 'fail_ape' => 'WARNING', - ), + ), // AU - audio - NeXT/Sun AUdio (AU) @@ -466,7 +480,7 @@ class getID3 'group' => 'audio', 'module' => 'au', 'mime_type' => 'audio/basic', - ), + ), // AVR - audio - Audio Visual Research 'avr' => array( @@ -474,7 +488,7 @@ class getID3 'group' => 'audio', 'module' => 'avr', 'mime_type' => 'application/octet-stream', - ), + ), // BONK - audio - Bonk v0.9+ 'bonk' => array( @@ -482,7 +496,7 @@ class getID3 'group' => 'audio', 'module' => 'bonk', 'mime_type' => 'audio/xmms-bonk', - ), + ), // FLAC - audio - Free Lossless Audio Codec 'flac' => array( @@ -490,7 +504,7 @@ class getID3 'group' => 'audio', 'module' => 'flac', 'mime_type' => 'audio/x-flac', - ), + ), // LA - audio - Lossless Audio (LA) 'la' => array( @@ -498,7 +512,7 @@ class getID3 'group' => 'audio', 'module' => 'la', 'mime_type' => 'application/octet-stream', - ), + ), // LPAC - audio - Lossless Predictive Audio Compression (LPAC) 'lpac' => array( @@ -506,7 +520,7 @@ class getID3 'group' => 'audio', 'module' => 'lpac', 'mime_type' => 'application/octet-stream', - ), + ), // MIDI - audio - MIDI (Musical Instrument Digital Interface) 'midi' => array( @@ -514,7 +528,7 @@ class getID3 'group' => 'audio', 'module' => 'midi', 'mime_type' => 'audio/midi', - ), + ), // MAC - audio - Monkey's Audio Compressor 'mac' => array( @@ -522,7 +536,7 @@ class getID3 'group' => 'audio', 'module' => 'monkey', 'mime_type' => 'application/octet-stream', - ), + ), // MOD - audio - MODule (assorted sub-formats) 'mod' => array( @@ -531,7 +545,7 @@ class getID3 'module' => 'mod', 'option' => 'mod', 'mime_type' => 'audio/mod', - ), + ), // MOD - audio - MODule (Impulse Tracker) 'it' => array( @@ -540,7 +554,7 @@ class getID3 'module' => 'mod', 'option' => 'it', 'mime_type' => 'audio/it', - ), + ), // MOD - audio - MODule (eXtended Module, various sub-formats) 'xm' => array( @@ -549,7 +563,7 @@ class getID3 'module' => 'mod', 'option' => 'xm', 'mime_type' => 'audio/xm', - ), + ), // MOD - audio - MODule (ScreamTracker) 's3m' => array( @@ -558,7 +572,7 @@ class getID3 'module' => 'mod', 'option' => 's3m', 'mime_type' => 'audio/s3m', - ), + ), // MPC - audio - Musepack / MPEGplus 'mpc' => array( @@ -566,7 +580,7 @@ class getID3 'group' => 'audio', 'module' => 'mpc', 'mime_type' => 'application/octet-stream', - ), + ), // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS) 'mp3' => array( @@ -574,7 +588,7 @@ class getID3 'group' => 'audio', 'module' => 'mp3', 'mime_type' => 'audio/mpeg', - ), + ), // OFR - audio - OptimFROG 'ofr' => array( @@ -582,7 +596,7 @@ class getID3 'group' => 'audio', 'module' => 'optimfrog', 'mime_type' => 'application/octet-stream', - ), + ), // RKAU - audio - RKive AUdio compressor 'rkau' => array( @@ -590,7 +604,7 @@ class getID3 'group' => 'audio', 'module' => 'rkau', 'mime_type' => 'application/octet-stream', - ), + ), // SHN - audio - Shorten 'shn' => array( @@ -600,7 +614,7 @@ class getID3 'mime_type' => 'audio/xmms-shn', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org) 'tta' => array( @@ -608,7 +622,7 @@ class getID3 'group' => 'audio', 'module' => 'tta', 'mime_type' => 'application/octet-stream', - ), + ), // VOC - audio - Creative Voice (VOC) 'voc' => array( @@ -616,7 +630,7 @@ class getID3 'group' => 'audio', 'module' => 'voc', 'mime_type' => 'audio/voc', - ), + ), // VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF) 'vqf' => array( @@ -624,7 +638,7 @@ class getID3 'group' => 'audio', 'module' => 'vqf', 'mime_type' => 'application/octet-stream', - ), + ), // WV - audio - WavPack (v4.0+) 'wv' => array( @@ -632,7 +646,7 @@ class getID3 'group' => 'audio', 'module' => 'wavpack', 'mime_type' => 'application/octet-stream', - ), + ), // Audio-Video formats @@ -644,15 +658,23 @@ class getID3 'module' => 'asf', 'mime_type' => 'video/x-ms-asf', 'iconv_req' => false, - ), + ), - // BINK - audio/video - Bink / Smacker + // BINK - audio/video - Bink / Smacker 'bink' => array( 'pattern' => '^(BIK|SMK)', 'group' => 'audio-video', 'module' => 'bink', 'mime_type' => 'application/octet-stream', - ), + ), + + // FLV - audio/video - FLash Video + 'flv' => array(
+ 'pattern' => '^FLV\x01',
+ 'group' => 'audio-video',
+ 'module' => 'flv',
+ 'mime_type' => 'video/x-flv',
+ ),
// MKAV - audio/video - Mastroka 'matroska' => array( @@ -660,7 +682,7 @@ class getID3 'group' => 'audio-video', 'module' => 'matroska', 'mime_type' => 'application/octet-stream', - ), + ), // MPEG - audio/video - MPEG (Moving Pictures Experts Group) 'mpeg' => array( @@ -668,7 +690,7 @@ class getID3 'group' => 'audio-video', 'module' => 'mpeg', 'mime_type' => 'video/mpeg', - ), + ), // NSV - audio/video - Nullsoft Streaming Video (NSV) 'nsv' => array( @@ -676,7 +698,7 @@ class getID3 'group' => 'audio-video', 'module' => 'nsv', 'mime_type' => 'application/octet-stream', - ), + ), // Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*)) 'ogg' => array( @@ -686,7 +708,7 @@ class getID3 'mime_type' => 'application/ogg', 'fail_id3' => 'WARNING', 'fail_ape' => 'WARNING', - ), + ), // QT - audio/video - Quicktime 'quicktime' => array( @@ -694,7 +716,7 @@ class getID3 'group' => 'audio-video', 'module' => 'quicktime', 'mime_type' => 'video/quicktime', - ), + ), // RIFF - audio/video - Resource Interchange File Format (RIFF) / WAV / AVI / CD-audio / SDSS = renamed variant used by SmartSound QuickTracks (www.smartsound.com) / FORM = Audio Interchange File Format (AIFF) 'riff' => array( @@ -703,7 +725,7 @@ class getID3 'module' => 'riff', 'mime_type' => 'audio/x-wave', 'fail_ape' => 'WARNING', - ), + ), // Real - audio/video - RealAudio, RealVideo 'real' => array( @@ -711,7 +733,7 @@ class getID3 'group' => 'audio-video', 'module' => 'real', 'mime_type' => 'audio/x-realaudio', - ), + ), // SWF - audio/video - ShockWave Flash 'swf' => array( @@ -719,7 +741,7 @@ class getID3 'group' => 'audio-video', 'module' => 'swf', 'mime_type' => 'application/x-shockwave-flash', - ), + ), // Still-Image formats @@ -732,7 +754,7 @@ class getID3 'mime_type' => 'image/bmp', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // GIF - still image - Graphics Interchange Format 'gif' => array( @@ -742,7 +764,7 @@ class getID3 'mime_type' => 'image/gif', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // JPEG - still image - Joint Photographic Experts Group (JPEG) 'jpg' => array( @@ -752,7 +774,7 @@ class getID3 'mime_type' => 'image/jpeg', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // PCD - still image - Kodak Photo CD 'pcd' => array( @@ -762,7 +784,7 @@ class getID3 'mime_type' => 'image/x-photo-cd', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // PNG - still image - Portable Network Graphics (PNG) @@ -773,7 +795,7 @@ class getID3 'mime_type' => 'image/png', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // TIFF - still image - Tagged Information File Format (TIFF) @@ -784,7 +806,7 @@ class getID3 'mime_type' => 'image/tiff', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // Data formats @@ -798,7 +820,7 @@ class getID3 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', 'iconv_req' => false, - ), + ), // RAR - data - RAR compressed data 'rar' => array( @@ -808,7 +830,7 @@ class getID3 'mime_type' => 'application/octet-stream', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // SZIP - audio - SZIP compressed data 'szip' => array( @@ -818,7 +840,7 @@ class getID3 'mime_type' => 'application/octet-stream', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // TAR - data - TAR compressed data 'tar' => array( @@ -828,7 +850,7 @@ class getID3 'mime_type' => 'application/x-tar', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // GZIP - data - GZIP compressed data 'gz' => array( @@ -838,7 +860,7 @@ class getID3 'mime_type' => 'application/x-gzip', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', - ), + ), // ZIP - data - ZIP compressed data 'zip' => array( diff --git a/modules/id3/getid3/module.audio-video.asf.php b/modules/id3/getid3/module.audio-video.asf.php index c11a04b2..c7e5aa1b 100644 --- a/modules/id3/getid3/module.audio-video.asf.php +++ b/modules/id3/getid3/module.audio-video.asf.php @@ -754,6 +754,11 @@ class getid3_asf $thisfile_asf_comments['year'] = array( $this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); break; + case 'wm/lyrics': + case 'lyrics': + $thisfile_asf_comments['lyrics'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + case 'isvbr': if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']) { $thisfile_audio['bitrate_mode'] = 'vbr'; @@ -769,12 +774,12 @@ class getid3_asf $tempThisfileInfo = array('encoding'=>$ThisFileInfo['encoding']); fwrite($tempfilehandle, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); fclose($tempfilehandle); - + $tempfilehandle = fopen($tempfile, "rb"); $id3 = new getid3_id3v2($tempfilehandle, $tempThisfileInfo); fclose($tempfilehandle); unlink($tempfile); - + $ThisFileInfo['id3v2'] = $tempThisfileInfo['id3v2']; } break; diff --git a/modules/id3/getid3/module.audio-video.flv.php b/modules/id3/getid3/module.audio-video.flv.php new file mode 100644 index 00000000..54666bd2 --- /dev/null +++ b/modules/id3/getid3/module.audio-video.flv.php @@ -0,0 +1,210 @@ +<?php +///////////////////////////////////////////////////////////////// +/// getID3() by James Heinrich <info@getid3.org> // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +// // +// FLV module by Seth Kaufman <seth@whirl-i-gig.com> // +// * version 0.1 (26 June 2005) // +// minor modifications by James Heinrich <info@getid3.org> // +// * version 0.1.1 (15 July 2005) // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.flv.php // +// module for analyzing Shockwave Flash Video files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + + +class getid3_flv +{ + + function getid3_flv(&$fd, &$ThisFileInfo, $ReturnAllTagData=false) { + fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); + + $FLVfileData = fread($fd, $ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']); + + $FLVmagic = substr($FLVfileData, 0, 3); + if ($FLVmagic != 'FLV') { + $ThisFileInfo['error'][] = 'Expecting "FLV" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$ThisFileInfo['flv']['header']['signature'].'"'; + unset($ThisFileInfo['flv']); + unset($ThisFileInfo['fileformat']); + return false; + } + $ThisFileInfo['flv']['header']['signature'] = $FLVmagic; + $ThisFileInfo['flv']['header']['version'] = ord($FLVfileData{3}); + $ThisFileInfo['fileformat'] = 'flv'; + + $TypeFlags = ord($FLVfileData{4}); + $ThisFileInfo['flv']['header']['hasAudio'] = (bool) ($TypeFlags & 4); + $ThisFileInfo['flv']['header']['hasVideo'] = (bool) ($TypeFlags & 1); + + $FrameSizeDataLength = getid3_lib::BigEndian2Int(substr($FLVfileData, 5, 4)); + + // FLV tags + $CurrentOffset = $FrameSizeDataLength; + $FLVdataLength = strlen($FLVfileData); + + $Duration = 0; + + $SoundFormat = null; + $VideoFormat = null; + while ($CurrentOffset < $FLVdataLength) { + // previous tag size + $PreviousTagLength = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset, 4)); + $CurrentOffset += 4; + + $TagType = ord(substr($FLVfileData, $CurrentOffset, 1)); + $DataLength = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 1, 3)); + $Timestamp = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 4, 3)); + + switch ($TagType) { + case 8: + if (is_null($SoundFormat)) { + $SoundInfo = ord(substr($FLVfileData, $CurrentOffset + 11, 1)); + $SoundFormat = $SoundInfo & 0x07; + $ThisFileInfo['flv']['audio']['audioFormat'] = $SoundFormat; + $ThisFileInfo['flv']['audio']['audioRate'] = ($SoundInfo & 0x30) / 0x10; + $ThisFileInfo['flv']['audio']['audioSampleSize'] = ($SoundInfo & 0x40) / 0x40; + $ThisFileInfo['flv']['audio']['audioType'] = ($SoundInfo & 0x80) / 0x80; + } + break; + + case 9: + if (is_null($VideoFormat)) { + $VideoInfo = ord(substr($FLVfileData, $CurrentOffset + 11, 1)); + $VideoFormat = $VideoInfo & 0x07; + $ThisFileInfo['flv']['video']['videoCodec'] = $VideoFormat; + + $PictureSizeType = (getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 15, 2))) >> 7; + $PictureSizeType = $PictureSizeType & 0x0007; + $ThisFileInfo['flv']['header']['videoSizeType'] = $PictureSizeType; + switch ($PictureSizeType) { + case 0: + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 16, 2)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_x'] = ($PictureSizeEnc & 0xFF00) >> 8; + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 17, 2)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_y'] = ($PictureSizeEnc & 0xFF00) >> 8; + break; + + case 1: + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 16, 4)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_x'] = ($PictureSizeEnc & 0xFFFF0000) >> 16; + + $PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVfileData, $CurrentOffset + 18, 4)); + $PictureSizeEnc <<= 1; + $ThisFileInfo['video']['resolution_y'] = ($PictureSizeEnc & 0xFFFF0000) >> 16; + break; + + case 2: + $ThisFileInfo['video']['resolution_x'] = 352; + $ThisFileInfo['video']['resolution_y'] = 288; + break; + + case 3: + $ThisFileInfo['video']['resolution_x'] = 176; + $ThisFileInfo['video']['resolution_y'] = 144; + break; + + case 4: + $ThisFileInfo['video']['resolution_x'] = 128; + $ThisFileInfo['video']['resolution_y'] = 96; + break; + + case 5: + $ThisFileInfo['video']['resolution_x'] = 320; + $ThisFileInfo['video']['resolution_y'] = 240; + break; + + case 6: + $ThisFileInfo['video']['resolution_x'] = 160; + $ThisFileInfo['video']['resolution_y'] = 120; + break; + + default: + $ThisFileInfo['video']['resolution_x'] = 0; + $ThisFileInfo['video']['resolution_y'] = 0; + break; + + } + } + break; + + default: + // noop + break; + } + + if ($Timestamp > $Duration) { + $Duration = $Timestamp; + } + + $CurrentOffset += ($DataLength + 11); + } + + $ThisFileInfo['playtime_seconds'] = $Duration / 1000; + $ThisFileInfo['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds']; + + if ($ThisFileInfo['flv']['header']['hasAudio']) { + $ThisFileInfo['audio']['codec'] = $this->FLVaudioFormat($ThisFileInfo['flv']['audio']['audioFormat']); + $ThisFileInfo['audio']['sample_rate'] = $this->FLVaudioRate($ThisFileInfo['flv']['audio']['audioRate']); + $ThisFileInfo['audio']['bits_per_sample'] = $this->FLVaudioBitDepth($ThisFileInfo['flv']['audio']['audioSampleSize']); + + $ThisFileInfo['audio']['channels'] = $ThisFileInfo['flv']['audio']['audioType'] + 1; // 0=mono,1=stereo + $ThisFileInfo['audio']['lossless'] = ($ThisFileInfo['flv']['audio']['audioFormat'] ? false : true); // 0=uncompressed + $ThisFileInfo['audio']['dataformat'] = 'flv'; + } + if (@$ThisFileInfo['flv']['header']['hasVideo']) { + $ThisFileInfo['video']['codec'] = $this->FLVvideoCodec($ThisFileInfo['flv']['video']['videoCodec']); + $ThisFileInfo['video']['dataformat'] = 'flv'; + $ThisFileInfo['video']['lossless'] = false; + } + + return true; + } + + + function FLVaudioFormat($id) { + $FLVaudioFormat = array( + 0 => 'uncompressed', + 1 => 'ADPCM', + 2 => 'mp3', + 5 => 'Nellymoser 8kHz mono', + 6 => 'Nellymoser', + ); + return (@$FLVaudioFormat[$id] ? @$FLVaudioFormat[$id] : false); + } + + function FLVaudioRate($id) { + $FLVaudioRate = array( + 0 => 5500, + 1 => 11025, + 2 => 22050, + 3 => 44100, + ); + return (@$FLVaudioRate[$id] ? @$FLVaudioRate[$id] : false); + } + + function FLVaudioBitDepth($id) { + $FLVaudioBitDepth = array( + 0 => 8, + 1 => 16, + ); + return (@$FLVaudioBitDepth[$id] ? @$FLVaudioBitDepth[$id] : false); + } + + function FLVvideoCodec($id) { + $FLVaudioBitDepth = array( + 2 => 'Sorenson H.263', + 3 => 'Screen video', + ); + return (@$FLVaudioBitDepth[$id] ? @$FLVaudioBitDepth[$id] : false); + } + +} + +?>
\ No newline at end of file diff --git a/modules/id3/getid3/module.audio-video.riff.php b/modules/id3/getid3/module.audio-video.riff.php index ebe3ee77..b2225a28 100644 --- a/modules/id3/getid3/module.audio-video.riff.php +++ b/modules/id3/getid3/module.audio-video.riff.php @@ -1953,8 +1953,6 @@ class getid3_riff XMPG Xing MPEG (I-Frame only) XVID XviD MPEG-4 (www.xvid.org) XXAN ?XXAN? - Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera - Y800 Simple, single Y plane for monochrome images YU92 Intel YUV (YU92) YUNV Nvidia Uncompressed YUV 4:2:2 YUVP Extended PAL format YUV palette (www.riff.org) @@ -1965,6 +1963,8 @@ class getid3_riff Y41T Brooktree PC1 YUV 4:1:1 with transparency Y42B Weitek YUV 4:2:2 Planar Y42T Brooktree UYUV 4:2:2 with transparency + Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera + Y800 Simple, single Y plane for monochrome images Y8 Grayscale video YC12 Intel YUV 12 codec YUV8 Winnov Caviar YUV8 diff --git a/modules/id3/getid3/module.audio.mp3.php b/modules/id3/getid3/module.audio.mp3.php index d7b0b77a..5fb6110c 100644 --- a/modules/id3/getid3/module.audio.mp3.php +++ b/modules/id3/getid3/module.audio.mp3.php @@ -320,8 +320,9 @@ class getid3_mp3 'fast standard|19000' => 19000, 'r3mix|19500' => 19500, // 3.90, 3.90.1, 3.92 'r3mix|19600' => 19600, // 3.90.2, 3.90.3, 3.91 - 'r3mix|18000' => 18000); // 3.94, 3.95 - if (!isset($ExpectedLowpass[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']])) { + 'r3mix|18000' => 18000, // 3.94, 3.95 + ); + if (!isset($ExpectedLowpass[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']]) && ($thisfile_mpeg_audio_lame['lowpass_frequency'] < 22050) && (round($thisfile_mpeg_audio_lame['lowpass_frequency'] / 1000) < round($thisfile_mpeg_audio['sample_rate'] / 2000))) { $encoder_options .= ' --lowpass '.$thisfile_mpeg_audio_lame['lowpass_frequency']; } break; @@ -1636,23 +1637,17 @@ class getid3_mp3 if (isset($MPEGaudioVersionLookup[$rawarray['version']])) { $decodedVersion = $MPEGaudioVersionLookup[$rawarray['version']]; } else { - if ($echoerrors) { - echo "\n".'invalid Version ('.$rawarray['version'].')'; - } + echo ($echoerrors ? "\n".'invalid Version ('.$rawarray['version'].')' : ''); return false; } if (isset($MPEGaudioLayerLookup[$rawarray['layer']])) { $decodedLayer = $MPEGaudioLayerLookup[$rawarray['layer']]; } else { - if ($echoerrors) { - echo "\n".'invalid Layer ('.$rawarray['layer'].')'; - } + echo ($echoerrors ? "\n".'invalid Layer ('.$rawarray['layer'].')' : ''); return false; } if (!isset($MPEGaudioBitrateLookup[$decodedVersion][$decodedLayer][$rawarray['bitrate']])) { - if ($echoerrors) { - echo "\n".'invalid Bitrate ('.$rawarray['bitrate'].')'; - } + echo ($echoerrors ? "\n".'invalid Bitrate ('.$rawarray['bitrate'].')' : ''); if ($rawarray['bitrate'] == 15) { // known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0 // let it go through here otherwise file will not be identified @@ -1664,27 +1659,19 @@ class getid3_mp3 } } if (!isset($MPEGaudioFrequencyLookup[$decodedVersion][$rawarray['sample_rate']])) { - if ($echoerrors) { - echo "\n".'invalid Frequency ('.$rawarray['sample_rate'].')'; - } + echo ($echoerrors ? "\n".'invalid Frequency ('.$rawarray['sample_rate'].')' : ''); return false; } if (!isset($MPEGaudioChannelModeLookup[$rawarray['channelmode']])) { - if ($echoerrors) { - echo "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')'; - } + echo ($echoerrors ? "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')' : ''); return false; } if (!isset($MPEGaudioModeExtensionLookup[$decodedLayer][$rawarray['modeextension']])) { - if ($echoerrors) { - echo "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')'; - } + echo ($echoerrors ? "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')' : ''); return false; } if (!isset($MPEGaudioEmphasisLookup[$rawarray['emphasis']])) { - if ($echoerrors) { - echo "\n".'invalid Emphasis ('.$rawarray['emphasis'].')'; - } + echo ($echoerrors ? "\n".'invalid Emphasis ('.$rawarray['emphasis'].')' : ''); return false; } // These are just either set or not set, you can't mess that up :) diff --git a/modules/id3/getid3/module.tag.id3v2.php b/modules/id3/getid3/module.tag.id3v2.php index c855bf21..8bb6c3cb 100644 --- a/modules/id3/getid3/module.tag.id3v2.php +++ b/modules/id3/getid3/module.tag.id3v2.php @@ -101,47 +101,51 @@ class getid3_id3v2 $thisfile_id3v2['tag_offset_start'] = $StartingOffset; $thisfile_id3v2['tag_offset_end'] = $thisfile_id3v2['tag_offset_start'] + $thisfile_id3v2['headerlength']; - // Extended Header + // Extended Header if (isset($thisfile_id3v2_flags['exthead']) && $thisfile_id3v2_flags['exthead']) { - // Extended header size 4 * %0xxxxxxx - // Number of flag bytes $01 - // Extended Flags $xx - // Where the 'Extended header size' is the size of the whole extended header, stored as a 32 bit synchsafe integer. - $extheader = fread ($fd, 4); - $thisfile_id3v2['extheaderlength'] = getid3_lib::BigEndian2Int($extheader, 1); - - // The extended flags field, with its size described by 'number of flag bytes', is defined as: - // %0bcd0000 - // b - Tag is an update - // Flag data length $00 - // c - CRC data present - // Flag data length $05 - // Total frame CRC 5 * %0xxxxxxx - // d - Tag restrictions - // Flag data length $01 - $extheaderflagbytes = fread ($fd, 1); - $extheaderflags = fread ($fd, $extheaderflagbytes); - $id3_exthead_flags = getid3_lib::BigEndian2Bin(substr($header, 5, 1)); - $thisfile_id3v2['exthead_flags']['update'] = substr($id3_exthead_flags, 1, 1); - $thisfile_id3v2['exthead_flags']['CRC'] = substr($id3_exthead_flags, 2, 1); - if ($thisfile_id3v2['exthead_flags']['CRC']) { - $extheaderrawCRC = fread ($fd, 5); - $thisfile_id3v2['exthead_flags']['CRC'] = getid3_lib::BigEndian2Int($extheaderrawCRC, 1); - } - $thisfile_id3v2['exthead_flags']['restrictions'] = substr($id3_exthead_flags, 3, 1); - if ($thisfile_id3v2['exthead_flags']['restrictions']) { - // Restrictions %ppqrrstt - $extheaderrawrestrictions = fread ($fd, 1); - $thisfile_id3v2['exthead_flags']['restrictions_tagsize'] = (bindec('11000000') & ord($extheaderrawrestrictions)) >> 6; // p - Tag size restrictions - $thisfile_id3v2['exthead_flags']['restrictions_textenc'] = (bindec('00100000') & ord($extheaderrawrestrictions)) >> 5; // q - Text encoding restrictions - $thisfile_id3v2['exthead_flags']['restrictions_textsize'] = (bindec('00011000') & ord($extheaderrawrestrictions)) >> 3; // r - Text fields size restrictions - $thisfile_id3v2['exthead_flags']['restrictions_imgenc'] = (bindec('00000100') & ord($extheaderrawrestrictions)) >> 2; // s - Image encoding restrictions - $thisfile_id3v2['exthead_flags']['restrictions_imgsize'] = (bindec('00000011') & ord($extheaderrawrestrictions)) >> 0; // t - Image size restrictions + // Extended header size 4 * %0xxxxxxx + // Number of flag bytes $01 + // Extended Flags $xx + // Where the 'Extended header size' is the size of the whole extended header, stored as a 32 bit synchsafe integer. + $thisfile_id3v2['exthead_length'] = getid3_lib::BigEndian2Int(fread($fd, 4), 1); + + $thisfile_id3v2['exthead_flag_bytes'] = ord(fread($fd, 1)); + if ($thisfile_id3v2['exthead_flag_bytes'] == 1) { + // The extended flags field, with its size described by 'number of flag bytes', is defined as: + // %0bcd0000 + // b - Tag is an update + // Flag data length $00 + // c - CRC data present + // Flag data length $05 + // Total frame CRC 5 * %0xxxxxxx + // d - Tag restrictions + // Flag data length $01 + $extheaderflags = fread($fd, $thisfile_id3v2['exthead_flag_bytes']); + $id3_exthead_flags = getid3_lib::BigEndian2Bin(substr($header, 5, 1)); + $thisfile_id3v2['exthead_flags']['update'] = substr($id3_exthead_flags, 1, 1); + $thisfile_id3v2['exthead_flags']['CRC'] = substr($id3_exthead_flags, 2, 1); + if ($thisfile_id3v2['exthead_flags']['CRC']) { + $extheaderrawCRC = fread($fd, 5); + $thisfile_id3v2['exthead_flags']['CRC'] = getid3_lib::BigEndian2Int($extheaderrawCRC, 1); + } + $thisfile_id3v2['exthead_flags']['restrictions'] = substr($id3_exthead_flags, 3, 1); + if ($thisfile_id3v2['exthead_flags']['restrictions']) { + // Restrictions %ppqrrstt + $extheaderrawrestrictions = fread($fd, 1); + $thisfile_id3v2['exthead_flags']['restrictions_tagsize'] = (bindec('11000000') & ord($extheaderrawrestrictions)) >> 6; // p - Tag size restrictions + $thisfile_id3v2['exthead_flags']['restrictions_textenc'] = (bindec('00100000') & ord($extheaderrawrestrictions)) >> 5; // q - Text encoding restrictions + $thisfile_id3v2['exthead_flags']['restrictions_textsize'] = (bindec('00011000') & ord($extheaderrawrestrictions)) >> 3; // r - Text fields size restrictions + $thisfile_id3v2['exthead_flags']['restrictions_imgenc'] = (bindec('00000100') & ord($extheaderrawrestrictions)) >> 2; // s - Image encoding restrictions + $thisfile_id3v2['exthead_flags']['restrictions_imgsize'] = (bindec('00000011') & ord($extheaderrawrestrictions)) >> 0; // t - Image size restrictions + } + } else { + $ThisFileInfo['warning'][] = '$thisfile_id3v2[exthead_flag_bytes] = "'.$thisfile_id3v2['exthead_flag_bytes'].'" (expecting "1")'; + fseek($fd, $thisfile_id3v2['exthead_length'] - 1, SEEK_CUR); + //return false; } } // end extended header - // create 'encoding' key - used by getid3::HandleAllTags() // in ID3v2 every field can have it's own encoding type // so force everything to UTF-8 so it can be handled consistantly @@ -159,10 +163,10 @@ class getid3_id3v2 // Flags $xx xx $sizeofframes = $thisfile_id3v2['headerlength'] - 10; // not including 10-byte initial header - if (isset($thisfile_id3v2['extheaderlength'])) { - $sizeofframes -= $thisfile_id3v2['extheaderlength']; + if (@$thisfile_id3v2['exthead_length']) { + $sizeofframes -= ($thisfile_id3v2['exthead_length'] + 4); } - if (isset($thisfile_id3v2_flags['isfooter']) && $thisfile_id3v2_flags['isfooter']) { + if (@$thisfile_id3v2_flags['isfooter']) { $sizeofframes -= 10; // footer takes last 10 bytes of ID3v2 header, after frame data, before audio } if ($sizeofframes > 0) { @@ -170,7 +174,7 @@ class getid3_id3v2 $framedata = fread($fd, $sizeofframes); // read all frames from file into $framedata variable // if entire frame data is unsynched, de-unsynch it now (ID3v2.3.x) - if (isset($thisfile_id3v2_flags['unsynch']) && $thisfile_id3v2_flags['unsynch'] && ($id3v2_majorversion <= 3)) { + if (@$thisfile_id3v2_flags['unsynch'] && ($id3v2_majorversion <= 3)) { $framedata = $this->DeUnsynchronise($framedata); } // [in ID3v2.4.0] Unsynchronisation [S:6.1] is done on frame level, instead @@ -179,7 +183,7 @@ class getid3_id3v2 // there exists an unsynchronised frame, while the new unsynchronisation flag in // the frame header [S:4.1.2] indicates unsynchronisation. - $framedataoffset = 10; // how many bytes into the stream - start from after the 10-byte header + $framedataoffset = 10 + (@$thisfile_id3v2['exthead_length'] ? $thisfile_id3v2['exthead_length'] + 4 : 0); // how many bytes into the stream - start from after the 10-byte header (and extended header length+4, if present) while (isset($framedata) && (strlen($framedata) > 0)) { // cycle through until no more frame data is left to parse if (strlen($framedata) <= $this->ID3v2HeaderLength($id3v2_majorversion)) { // insufficient room left in ID3v2 header for actual data - must be padding @@ -350,7 +354,7 @@ class getid3_id3v2 // ID3v2 size 4 * %0xxxxxxx if (isset($thisfile_id3v2_flags['isfooter']) && $thisfile_id3v2_flags['isfooter']) { - $footer = fread ($fd, 10); + $footer = fread($fd, 10); if (substr($footer, 0, 3) == '3DI') { $thisfile_id3v2['footer'] = true; $thisfile_id3v2['majorversion_footer'] = ord($footer{3}); diff --git a/modules/id3/getid3/write.id3v2.php b/modules/id3/getid3/write.id3v2.php index a575f20b..9d47e708 100644 --- a/modules/id3/getid3/write.id3v2.php +++ b/modules/id3/getid3/write.id3v2.php @@ -101,6 +101,7 @@ class getid3_write_id3v2 fclose($fp_source); copy($tempfilename, $this->filename); unlink($tempfilename); + ob_end_clean(); return true; } else { diff --git a/modules/id3/getid3/write.php b/modules/id3/getid3/write.php index 40a79e9e..db09decd 100644 --- a/modules/id3/getid3/write.php +++ b/modules/id3/getid3/write.php @@ -394,6 +394,14 @@ class getid3_writetags } break; + case 'real': + $real_writer = new getid3_write_real; + $real_writer->filename = $this->filename; + if (($success = $real_writer->RemoveReal()) === false) { + $this->errors[] = 'RemoveReal() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $real_writer->errors)).'</LI></UL></PRE>'; + } + break; + default: $this->errors[] = 'Invalid tag format to delete: "'.$tagformat.'"'; return false; diff --git a/modules/id3/getid3/write.real.php b/modules/id3/getid3/write.real.php index 5ede28d1..1e0240cc 100644 --- a/modules/id3/getid3/write.real.php +++ b/modules/id3/getid3/write.real.php @@ -16,7 +16,7 @@ class getid3_write_real { var $filename; - var $tag_data; + var $tag_data = array(); var $warnings = array(); // any non-critical errors will be stored here var $errors = array(); // any critical errors will be stored here var $paddedlength = 512; // minimum length of CONT tag in bytes @@ -33,50 +33,98 @@ class getid3_write_real // Initialize getID3 engine $getID3 = new getID3; $OldThisFileInfo = $getID3->analyze($this->filename); - if (empty($OldThisFileInfo['chunks']) && !empty($OldThisFileInfo['old_ra_header'])) { + if (empty($OldThisFileInfo['real']['chunks']) && !empty($OldThisFileInfo['real']['old_ra_header'])) { $this->errors[] = 'Cannot write Real tags on old-style file format'; + fclose($fp_source); return false; } - $OldPROPinfo = false; - $StartOfDATA = false; - foreach ($OldThisFileInfo['chunks'] as $chunknumber => $chunkarray) { - if ($chunkarray['name'] == 'PROP') { - $OldPROPinfo = $chunkarray; - } elseif ($chunkarray['name'] = 'DATA') { - $StartOfDATA = $chunkarray['offset']; - } + if (empty($OldThisFileInfo['real']['chunks'])) { + $this->errors[] = 'Cannot write Real tags because cannot find DATA chunk in file'; + fclose($fp_source); + return false; + } + foreach ($OldThisFileInfo['real']['chunks'] as $chunknumber => $chunkarray) { + $oldChunkInfo[$chunkarray['name']] = $chunkarray; + } + if (!empty($oldChunkInfo['CONT']['length'])) { + $this->paddedlength = max($oldChunkInfo['CONT']['length'], $this->paddedlength); } - if (!empty($OldPROPinfo['length'])) { - $this->paddedlength = max($OldPROPinfo['length'], $this->paddedlength); + $new_CONT_tag_data = $this->GenerateCONTchunk(); + $new_PROP_tag_data = $this->GeneratePROPchunk($OldThisFileInfo['real']['chunks'], $new_CONT_tag_data); + $new__RMF_tag_data = $this->GenerateRMFchunk($OldThisFileInfo['real']['chunks']); + + if (@$oldChunkInfo['.RMF']['length'] == strlen($new__RMF_tag_data)) { + fseek($fp_source, $oldChunkInfo['.RMF']['offset'], SEEK_SET); + fwrite($fp_source, $new__RMF_tag_data); + } else { + $this->errors[] = 'new .RMF tag ('.strlen($new__RMF_tag_data).' bytes) different length than old .RMF tag ('.$oldChunkInfo['.RMF']['length'].' bytes)'; + fclose($fp_source); + return false; } - $new_real_tag_data = GenerateRealTag(); + if (@$oldChunkInfo['PROP']['length'] == strlen($new_PROP_tag_data)) { + fseek($fp_source, $oldChunkInfo['PROP']['offset'], SEEK_SET); + fwrite($fp_source, $new_PROP_tag_data); + } else { + $this->errors[] = 'new PROP tag ('.strlen($new_PROP_tag_data).' bytes) different length than old PROP tag ('.$oldChunkInfo['PROP']['length'].' bytes)'; + fclose($fp_source); + return false; + } - if (@$OldPROPinfo['length'] == $new_real_tag_data) { + if (@$oldChunkInfo['CONT']['length'] == strlen($new_CONT_tag_data)) { // new data length is same as old data length - just overwrite - fseek($fp_source, $OldPROPinfo['offset'], SEEK_SET); - fwrite($fp_source, $new_real_tag_data); + fseek($fp_source, $oldChunkInfo['CONT']['offset'], SEEK_SET); + fwrite($fp_source, $new_CONT_tag_data); + fclose($fp_source); + return true; } else { - if (empty($OldPROPinfo)) { - // no existing PROP chunk - $BeforeOffset = $StartOfDATA; - $AfterOffset = $StartOfDATA; + if (empty($oldChunkInfo['CONT'])) { + // no existing CONT chunk + $BeforeOffset = $oldChunkInfo['DATA']['offset']; + $AfterOffset = $oldChunkInfo['DATA']['offset']; } else { // new data is longer than old data - $BeforeOffset = $OldPROPinfo['offset']; - $AfterOffset = $OldPROPinfo['offset'] + $OldPROPinfo['length']; + $BeforeOffset = $oldChunkInfo['CONT']['offset']; + $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; } + if ($tempfilename = tempnam('*', 'getID3')) { + ob_start(); + if ($fp_temp = fopen($tempfilename, 'wb')) { + + rewind($fp_source); + fwrite($fp_temp, fread($fp_source, $BeforeOffset)); + fwrite($fp_temp, $new_CONT_tag_data); + fseek($fp_source, $AfterOffset, SEEK_SET); + while ($buffer = fread($fp_source, GETID3_FREAD_BUFFER_SIZE)) { + fwrite($fp_temp, $buffer, strlen($buffer)); + } + fclose($fp_temp); + + if (copy($tempfilename, $this->filename)) { + unlink($tempfilename); + fclose($fp_source); + return true; + } + unlink($tempfilename); + $this->errors[] = 'FAILED: copy('.$tempfilename.', '.$this->filename.') - '.strip_tags(ob_get_contents()); + } else { + + $this->errors[] = 'Could not open '.$tempfilename.' mode "wb" - '.strip_tags(ob_get_contents()); + + } + ob_end_clean(); + } + fclose($fp_source); + return false; } - fclose($fp_source); - return true; } else { $this->errors[] = 'Could not open '.$this->filename.' mode "r+b"'; @@ -87,28 +135,88 @@ class getid3_write_real return false; } - function GenerateRealTag() { - $RealCONT = "\x00\x00"; // object version + function GenerateRMFchunk(&$chunks) { + $oldCONTexists = false; + foreach ($chunks as $key => $chunk) { + $chunkNameKeys[$chunk['name']] = $key; + if ($chunk['name'] == 'CONT') { + $oldCONTexists = true; + } + } + $newHeadersCount = $chunks[$chunkNameKeys['.RMF']]['headers_count'] + ($oldCONTexists ? 0 : 1); - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['title']), 4); - $RealCONT .= @$this->tag_data['title']; + $RMFchunk = "\x00\x00"; // object version + $RMFchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['.RMF']]['file_version'], 4); + $RMFchunk .= getid3_lib::BigEndian2String($newHeadersCount, 4); - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['artist']), 4); - $RealCONT .= @$this->tag_data['artist']; + $RMFchunk = '.RMF'.getid3_lib::BigEndian2String(strlen($RMFchunk) + 8, 4).$RMFchunk; // .RMF chunk identifier + chunk length + return $RMFchunk; + } + + function GeneratePROPchunk(&$chunks, &$new_CONT_tag_data) { + $old_CONT_length = 0; + $old_DATA_offset = 0; + $old_INDX_offset = 0; + foreach ($chunks as $key => $chunk) { + $chunkNameKeys[$chunk['name']] = $key; + if ($chunk['name'] == 'CONT') { + $old_CONT_length = $chunk['length']; + } elseif ($chunk['name'] == 'DATA') { + if (!$old_DATA_offset) { + $old_DATA_offset = $chunk['offset']; + } + } elseif ($chunk['name'] == 'INDX') { + if (!$old_INDX_offset) { + $old_INDX_offset = $chunk['offset']; + } + } + } + $CONTdelta = strlen($new_CONT_tag_data) - $old_CONT_length; - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['copyright']), 4); - $RealCONT .= @$this->tag_data['copyright']; + $PROPchunk = "\x00\x00"; // object version + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['max_bit_rate'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['avg_bit_rate'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['max_packet_size'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['avg_packet_size'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['num_packets'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['duration'], 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['preroll'], 4); + $PROPchunk .= getid3_lib::BigEndian2String(max(0, $old_INDX_offset + $CONTdelta), 4); + $PROPchunk .= getid3_lib::BigEndian2String(max(0, $old_DATA_offset + $CONTdelta), 4); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['num_streams'], 2); + $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['flags_raw'], 2); - $RealCONT .= BigEndian2String(strlen(@$this->tag_data['comment']), 4); - $RealCONT .= @$this->tag_data['comment']; + $PROPchunk = 'PROP'.getid3_lib::BigEndian2String(strlen($PROPchunk) + 8, 4).$PROPchunk; // PROP chunk identifier + chunk length + return $PROPchunk; + } - if ($this->paddedlength > (strlen($RealCONT) + 8)) { - $RealCONT .= str_repeat("\x00", $this->paddedlength - strlen($RealCONT) - 8); + function GenerateCONTchunk() { + foreach ($this->tag_data as $key => $value) { + // limit each value to 0xFFFF bytes + $this->tag_data[$key] = substr($value, 0, 65535); } - $RealCONT = 'CONT'.BigEndian2String(strlen($RealCONT) + 8, 4).$RealCONT; // CONT chunk identifier + chunk length + $CONTchunk = "\x00\x00"; // object version + + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['title']), 2); + $CONTchunk .= @$this->tag_data['title']; + + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['artist']), 2); + $CONTchunk .= @$this->tag_data['artist']; + + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['copyright']), 2); + $CONTchunk .= @$this->tag_data['copyright']; - return $RealCONT; + $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['comment']), 2); + $CONTchunk .= @$this->tag_data['comment']; + + if ($this->paddedlength > (strlen($CONTchunk) + 8)) { + $CONTchunk .= str_repeat("\x00", $this->paddedlength - strlen($CONTchunk) - 8); + } + + $CONTchunk = 'CONT'.getid3_lib::BigEndian2String(strlen($CONTchunk) + 8, 4).$CONTchunk; // CONT chunk identifier + chunk length + + return $CONTchunk; } function RemoveReal() { @@ -116,22 +224,69 @@ class getid3_write_real if (is_writeable($this->filename)) { if ($fp_source = @fopen($this->filename, 'r+b')) { -return false; - //fseek($fp_source, -128, SEEK_END); - //if (fread($fp_source, 3) == 'TAG') { - // ftruncate($fp_source, filesize($this->filename) - 128); - //} else { - // // no real tag to begin with - do nothing - //} + // Initialize getID3 engine + $getID3 = new getID3; + $OldThisFileInfo = $getID3->analyze($this->filename); + if (empty($OldThisFileInfo['real']['chunks']) && !empty($OldThisFileInfo['real']['old_ra_header'])) { + $this->errors[] = 'Cannot remove Real tags from old-style file format'; + fclose($fp_source); + return false; + } + + if (empty($OldThisFileInfo['real']['chunks'])) { + $this->errors[] = 'Cannot remove Real tags because cannot find DATA chunk in file'; + fclose($fp_source); + return false; + } + foreach ($OldThisFileInfo['real']['chunks'] as $chunknumber => $chunkarray) { + $oldChunkInfo[$chunkarray['name']] = $chunkarray; + } + + if (empty($oldChunkInfo['CONT'])) { + // no existing CONT chunk + fclose($fp_source); + return true; + } + + $BeforeOffset = $oldChunkInfo['CONT']['offset']; + $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; + if ($tempfilename = tempnam('*', 'getID3')) { + ob_start(); + if ($fp_temp = fopen($tempfilename, 'wb')) { + + rewind($fp_source); + fwrite($fp_temp, fread($fp_source, $BeforeOffset)); + fseek($fp_source, $AfterOffset, SEEK_SET); + while ($buffer = fread($fp_source, GETID3_FREAD_BUFFER_SIZE)) { + fwrite($fp_temp, $buffer, strlen($buffer)); + } + fclose($fp_temp); + + if (copy($tempfilename, $this->filename)) { + unlink($tempfilename); + fclose($fp_source); + return true; + } + unlink($tempfilename); + $this->errors[] = 'FAILED: copy('.$tempfilename.', '.$this->filename.') - '.strip_tags(ob_get_contents()); + + } else { + + $this->errors[] = 'Could not open '.$tempfilename.' mode "wb" - '.strip_tags(ob_get_contents()); + + } + ob_end_clean(); + } fclose($fp_source); - return true; + return false; + } else { $this->errors[] = 'Could not open '.$this->filename.' mode "r+b"'; + return false; } - } else { - $this->errors[] = $this->filename.' is not writeable'; } + $this->errors[] = 'File is not writeable: '.$this->filename; return false; } diff --git a/modules/init.php b/modules/init.php index fa57c29e..0fc904c4 100644 --- a/modules/init.php +++ b/modules/init.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or @@ -83,7 +83,7 @@ if (!$results['conf']['allow_stream_playback']) { $results['conf']['raw_web_path'] = $results['conf']['web_path']; $results['conf']['web_path'] = $http_type . $_SERVER['HTTP_HOST'] . $results['conf']['web_path']; -$results['conf']['version'] = '3.3.2-Beta1 (Build 001)'; +$results['conf']['version'] = '3.3.2-Beta1 (Build 002)'; $results['conf']['catalog_file_pattern']= 'mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx'; $results['libglue']['local_table'] = 'session'; $results['libglue']['local_sid'] = 'id'; diff --git a/modules/validatemail/validateEmail.php b/modules/validatemail/validateEmail.php new file mode 100644 index 00000000..e8cc037a --- /dev/null +++ b/modules/validatemail/validateEmail.php @@ -0,0 +1,638 @@ +<?php +/* +validateEmail.php +version 2.0 +by Clay Loveless <clay@killersoft.com> + + +Originally +By: Jon S. Stevens jon@clearink.com +Copyright 1998 Jon S. Stevens, Clear Ink +This code has all the normal disclaimers. +It is free for any use, just keep the credits intact. + +Enhancements and modifications: + + By: Shane Y. Gibson shane@tuna.org +Organization: The Unix Network Archives (http://www.tuna.org/) + Date: November 16th, 1998 + Changes: - Added **all** comments, as original code lacked them. + - Added some return codes to include a bit more description + for useability. + + By: berber +Organization: webdev.berber.co.il + Date: April 10th, 1999 + Changes: - The script now handles all kinds of domains (not only @xxx.yyy) as before. + - Added a debugging mode which also works as a verbose mode. + + By: Frank Vogel vogel@simec.com +Organization: Simec Corp. (http://www.simec.com) + Date: June 13th, 2000 + Changes: - Check for MX records for each qualification step of the domain name + - Use nobody@$SERVER_NAME as MAIL FROM: argument + Disclaimers: I disclaim nothing...nor do I claim anything...but + it would be nice if you included this disclaimer... + + + NOTE: berber and Frank Vogel made some of the same changes regarding + domain name checking to seperate versions of Shane Gibson's validateEmail variant. + Their changes have been merged into version 2.0. + + + By: Clay Loveless <clay@killersoft.com> +Organization: KillerSoft < http://www.killersoft.com/ > + Date: March 12th, 2002 + Changes: - Added 'Preferences' section, enabling several variables to be easily set + - Changed "nobody@$SERVER_NAME" for MAIL FROM: argument to be + "$from@$serverName" - set via Preferences section + - Signifcantly enhanced berber's 'debug' mode. It has become 'Verbose' mode + to ease debugging. + - Made 'Verbose' mode a function argument. Call validateEmail($email,1) to enable. + - Added environment detection - 'Verbose' output is adaptable to command-line + execution and embedded web execution. + - Added $socketTimeout Preferences variable for controlling how long we'll wait + during fsockopen() to any given host. + - Added $waitTimeout Preferences variable to control how long we'll wait for + a server we've successfully connected with to actually respond with an SMTP greeting. + Note -- this is a complete replacement of the previous "wait" method of simply + increasing a counter, which proved extremely inadequate in testing on sluggish hosts. + - Added $mxcutoff Preferences variable to control how many MX hosts we're willing to + talk to before calling it quits. (So we're not required to hear "no" from 14 + hotmail.com mail servers if we don't want to.) + - Added routine to check SMTP server greeting line for ESTMP, and respond accordingly + with EHLO. + - Added routines to listen for multi-line output from servers. + - Fixed all commands ending in "\n" to end in "\r\n" as specified by accurate SMTP + communication. THIS FIXES THE "HANG" PROBLEM EXPERIENCED WITH MANY MAIL SERVERS, + INCLUDING AOL.COM. (See Disclaimers about AOL.com connections, though ...) + - Added support for Jeffrey E.F. Friedl's definitive email format regex, translated + from perl into PHP. Will reject email addresses with invalid formatting before + opening any server connections. + - Changed initial "listening" routine to listen for one of two SMTP greeting responses + (220 or 421) instead of just listening for anything. validateEmail is now well-behaved + if a 421 "temporary rejection" code is received. + - Assorted optimizations -- using explode() instead of split(), preg_match() + instead of ereg(), etc. + - Improved error reporting on failures. + - Fixed typos in comments. : ) + - Modified comments where Shane Gibson's were no longer needed or accurate (due to changes). + Added the comments for features that didn't exist in Shane's version. + - Incremented version number. + + Disclaimers: - All additions and modifications Copyright 2002 KillerSoft.com. + - Program is free for any use as long as these notes & credits remain intact. + - Yes, I know there is no foolproof way to validate an e-mail address. But this is better than + nothing. + - Yes, I know that fewer and fewer mail servers are supporting the type of connection + and validation that this script performs. There are still a hell of a lot more of them + that DO support it than those that DON'T. Yes, this may change over time. + - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + - By using this code you agree to indemnify Clay Loveless, KillerSoft, and Crawlspace, Inc. + from any liability that might arise from its use. + - Use at your own risk. This may not work for you. It may produce results other than what you'd expect, + or even prefer. + - AOL.COM Disclaimer: As of this release, mail servers operated by AOL.com (netscape.com, + aol.com, cs.com, anything with aoltw.net, just to name a few) return "250" (recipient OK) codes for + _any_ address you throw at them. Bounces for invalid recipients are handled and sent out + through alternate means. So -- this script won't help you in validating AOL.com (and affiliated) + e-mail addresses. BUT ... at least it won't choke/hang on them either, as previous versions + of this script would. + + - Please send bugs, comments or suggestions to info@killersoft.com! +*/ + +/* This function takes in an email address (say 'shane@tuna.org') +* and tests to see if it's a valid email address. +* +* An array with the results is passed back to the caller. +* +* Possible result codes for the array items are: +* +* Item 0: [true|false] true for valid email address +* false for NON-valid email address +* +* Item 1: [SMTP Code] if a valid MX mail server found, then +* fill this array in with failed SMTP +* reply codes +* IF no MX mail server found or connected to, +* errors will be explained in this response. +* +* Possible Internal error messages: +* Invalid email address (bad domain name) [ default message from the old days ] +* fsockopen error $errno: $errstr +* 554 No MX records found for $domain +* 554 No DNS reverse record found for $domain +* +* (554 Response code borrowed from ESMTP's "Transaction failed" response) +* +* Item 2: [true|false] true for valid mail server found for +* host/domain +* false if no valid mail server found +* +* Item 3: [MX server] if a valid MX host was found and +* connected to then fill in this item +* with the MX server hostname +* +* EXAMPLE CODE for use is available at: +* http://www.killersoft.com/contrib/ +*/ + +function validateEmail ( $email, $verbose=0 ) { + global $SERVER_NAME; + + // DEFINE PREFERENCES + + // Passed along with the HELO/EHLO statement. + // Leave blank to use $SERVER_NAME. + // Note that most modern MTAs will ignore (but require) whatever you say here ... + // the server will determine your domain via other means. + if (conf('mail_domain')){ + $serverName = conf('mail_domain'); + } else { + $serverName = "domain.tld"; + } + // MAIL FROM -- who's asking? + // Good values: nobody, postmaster, info, buckwheat, gumby + $from = "info"; + + // fsockopen() timeout - in seconds + $socketTimeout = 15; + + // waitTimeout - how long we'll wait for a server to respond after + // a successful connection. In seconds. + // Recommended to keep this above 35 seconds - some servers are really slow. + $waitTimeout = 50; + + // MX Server cutoff + // Some hosts (like hotmail.com) have MANY MX hosts -- 12 or more. + // Set this to a number where you'd like to say "I get the picture" + // ... so you don't wind up having to hit EVERY MX host. + $mxcutoff = 15; + + // END OF PREFERENCES + + /////////////////////////////////////////////////////////////////////////////// + // DO NOT EDIT BELOW THIS LINE + /////////////////////////////////////////////////////////////////////////////// + + + // Default initiation statement + $send = "HELO"; + + // Let's give good commands + $CRLF = "\r\n"; + + // Make a few adjustments for verbose mode + if ( $verbose ) { + + // Version + $version = "validateEmail 2.0 - http://killersoft.com/contrib/"; + + // Start stopwatch + list ( $msecStart, $secStart ) = explode ( " ", microtime() ); + + // Adjust verbose output format + // for php.cgi or webserver interface + $sapi_type = php_sapi_name(); + if ( $sapi_type == "cgi" ) { + // format < > + $leftCarrot = "<"; + $rightCarrot = ">"; + // set type of "new line" + $vNL = "echo \"\n\";"; + // verbose Flush Only + $vFlush = ""; + // output for debugging + eval("echo \"Internal: $version - running as ".AddSlashes($sapi_type)."\"; $vNL"); + } else { + // format < > + $leftCarrot = "<"; + $rightCarrot = ">"; + // set type of "new line" ... flush output for web browsing + echo "<pre>"; + $vNL = "echo \"\n\"; flush();"; + // verbose Flush Only + $vFlush = "flush();"; + // output for debugging + eval("echo \"Internal: $version - running as ".AddSlashes($sapi_type)."\"; $vNL"); + } + } + + // How we'll identify ourselves in SMTP HELO/EHLO argument + if ( $serverName == "" ) $serverName = "$SERVER_NAME"; + if ( $serverName == "" ) $serverName = "localhost"; + + // Initialize return values with default + $return[0] = false; + $return[1] = "Invalid email address (bad domain name)"; + $return[2] = false; + $return[3] = ""; + + // make sure that we're dealing with a valid email address format + $isValid = true; // just in case validateEmailFormat is not available + if ( function_exists('validateEmailFormat') ) $isValid = validateEmailFormat ( $email ); + + // abort if necessary + if ( !$isValid ) { + if ( $verbose ) eval("echo \"Internal: $email format is invalid! Quitting ...\"; $vNL"); + return $return; + + } else { + if ( $verbose ) eval("echo \"Internal: $email is a valid RFC 822 formatted address\"; $vNL"); + + // assign our user part and domain parts respectively to seperate + // variables + list ( $user, $domain ) = explode ( "@", $email ); + if ( $verbose ) { + eval("echo \"Internal: user ..... $user\"; $vNL"); + eval("echo \"Internal: domain ... $domain\"; $vNL"); + } + + // split up the domain into sub-parts + $arr = explode ( ".", $domain ); + + // figure out how many parts there are in the host/domain name portion + $count = count ( $arr ); + + // flag to indicate success + $bSuccess = false; + + // we try this for each qualification step of domain name + // (from full qualified to TopLevel) + for ( $i = 0; $i < $count - 1 && !$bSuccess; $i = $i + 1 ) { + + // create the domain name + $domain = ""; + for ( $j = $i; $j < $count; $j = $j + 1 ) { + $domain = $domain . $arr[$j]; + if ( $j < $count - 1 ) + // tack on the last dot + $domain = $domain . "."; + } + if ( $verbose ) eval("echo \"Internal: checking DNS for $domain ... \"; $vNL"); + + // check that an MX record exists for Top-Level domain + // If it exists, start our email address checking + if ( checkdnsrr ( $domain, "MX" ) ) { + + // Okay -- we've got a valid DNS reverse record. + if ( $verbose ) eval("echo \"Internal: ... Check DNS RR OK!\"; $vNL"); + // Test that MX record for host exists, + // then fill 'mxhosts' and 'weight' arrays with correct info + if ( getmxrr ( $domain, $mxhosts, $weight ) ) { + + // Now we've got MX records + if ( $verbose ) { + eval("echo \"Internal: MX LOOKUP RESULTS:\"; $vNL"); + for ( $i = 0; $i < count ( $mxhosts ); $i++) { + eval("echo \" $mxhosts[$i]\"; $vNL"); + } + } + // sift through the 'mxhosts', connecting to each one + // ONLY until we get a good match + $mxcount = count( $mxhosts ); + // determine our MX host cutoff + $mxstop = ($mxcount > $mxcutoff) ? $mxcutoff : $mxcount; + for ( $i = 0; $i < $mxstop ; $i++ ) { + + // open socket on port 25 to mxhost, setting + // returned socket pointer to $sp + if( $verbose ) eval("echo \"Internal: attempting to open $mxhosts[$i] ...\"; $vNL"); + $sp = fsockopen ( $mxhosts[$i], 25, $errno, $errstr, $socketTimeout); + + // Greeting Code default + // Sets default greeting code to 421, just in case we + // don't ever hear ANYTHING from this host. + // If we hear nothing, we'll want to skip it. + $greetCode = "421"; + + // if $sp connection is good, let's rock on + if ( $sp ) { + if ( $verbose ) { + eval("echo \"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\"; $vNL"); + eval("echo \"Internal: socket open to $mxhosts[$i]\"; $vNL"); + } + // work variables + $waitMarker = 0; + $msec = 0; // milisec count + $tsec = 0; // tensec count + $out = ""; + + // set our created socket for $sp to + // non-blocking mode so that our fgets() + // calls will return with a quickness + set_socket_blocking ( $sp, false ); + + // as long as our 'out' variable does not begin + // with a valid SMTP greeting (220 or 421), + // keep looping (do) until we get something + do { + + // prepare for clean debug output if necessary + // (puts a line break after the waitMarkers) + if ( $verbose && $msec > 0 ) { + $elapsed = $tsec + ($msec/4); + $clean = "echo \"($elapsed seconds)\"; $vNL"; + } + // output of the stream assigned to + // 'out' variable + $out = fgets ( $sp, 2500 ); + + // Check for multi-line output (###-) + if ( preg_match ( "/^2..-/", $out ) ) { + $end = false; + while ( !$end ) { + // keep listening + $line = fgets ( $sp, 2500 ); + $out .= $line; + if ( preg_match ( "/^2.. /", $line ) ) { + // the last line of output shouldn't + // have a dash after the response code + $end = true; + } + } + } + + if ( $verbose && $out != "" ) eval("$clean echo \"Server: ".AddSlashes($out)."\"; $vNL"); + + // if we get a "220" code (service ready), + // we're ready to rock on + if ( substr ( $out, 0, 3 ) == "220" ) { + if ( $verbose ) eval("echo \"Internal: service ready on $mxhosts[$i] ... moving on\"; $vNL"); + $return[2] = true; + $return[3] = "$mxhosts[$i]"; + // determine if we should speak in terms of HELO or EHLO + if ( preg_match ( "/ESMTP/", $out ) ) { + $send = "HELO"; + } else { + $send = "HELO"; + } + + // Set Greeting Code + $greetCode = "220"; + + } + + // else if ... + // Perhaps we've gotten a 421 Temporarily Refused error + else if ( substr ( $out, 0, 3 ) == "421" ) { + + //if ( $verbose ) echo " ... moving on\n"; + if ( $verbose ) eval("echo \"Internal: $mxhosts[$i] temporarily rejected connection. (421 response)\"; $vNL"); + $return[2] = false; + // Set Greeting Code + $greetCode = "421"; + break; // get out of this loop + + } + + // increase our waitTimeout counters + // if we still haven't heard anything ... + // Note that the time looping isn't an exact science + // with usleep or the Windows hack ... but + // it's in the ballpark. Close enough. + if ( $out == "" && $msec < $waitTimeout ) { + + // wait for a quarter of a second + if ( $verbose ) { + if ( $msec == 0 ) { + eval("echo \"Internal: Waiting: one '.' ~ 0.25 seconds of waiting\"; $vNL"); + } + eval("echo \".\"; $vFlush"); + $waitMarker++; + if ( $waitMarker == 40 ) { + // ten seconds + $tsec += 10; + eval("echo \" ($tsec seconds)\"; $vNL"); + $waitMarker = 0; + } + } + $msec = $msec + 0.25; + usleep(250000); + + } elseif ( $msec == $waitTimeout ) { + + // let's get out of here. Toooo sloooooww ... + if ( $verbose ) eval("$clean echo \"Internal: !! we've waited $waitTimeout seconds !!\nbreaking ...\"; $vNL"); + break; + + } + + + // end of 'do' loop + } while ( substr ( $out, 0, 3 ) != "220" ); + + // Make sure we got a "220" greetCode + // before we start shoveling requests + // at this server. + if ( $greetCode == "220" ) { + + // reset our file pointer to blocking mode, + // so we can wait for communication to finish + // before moving on ... + set_socket_blocking ( $sp, true ); + + // talk to the MX mail server, attempt to validate + // ourself. Use "HELO" or "EHLO", as determined above + fputs ( $sp, "$send $serverName"."$CRLF" ); + if ( $verbose ) eval("echo \"Client: $send $serverName\"; $vNL"); + + // get the mail server's reply, check it + // + $originalOutput = fgets ( $sp, 2500 ); + // Check for multi-line positive output + if ( preg_match ( "/^...-/", $originalOutput ) ) { + $end = false; + while ( !$end ) { + // keep listening + $line = fgets ( $sp, 2500 ); + $originalOutput .= $line; + if ( preg_match ( "/^... /", $line ) ) { + // the last line of output shouldn't + // have a dash after the response code + $end = true; + } + } + } + if ( $verbose ) eval("echo \"Server: ".AddSlashes($originalOutput)."\"; $vNL"); + + + // if there's a HELP option, let's see it + if ( $verbose ) { + if( preg_match( "/250.HELP/m", $originalOutput ) && $verbose == true ) { + + eval("echo \"Internal: VERBOSE-MODE ONLY: Getting the HELP output\"; $vNL"); + // Get the output of the HELP command + fputs ( $sp, "HELP"."$CRLF" ); + if ( $verbose ) eval("echo \"Client: HELP\"; $vNL"); + // Get output again + $output = fgets ( $sp, 2500 ); + // Check for multi-line positive output + if ( preg_match ( "/^...-/", $output ) ) { + $end = false; + while ( !$end ) { + // keep listening + $line = fgets ( $sp, 2500 ); + $output .= $line; + if ( preg_match ( "/^... /", $line ) ) { + // the last line of output shouldn't + // have a dash after the response code + $end = true; + } + } + } + if ( $verbose ) eval("echo \"Server: ".AddSlashes($output)."\"; $vNL"); + + } + } + + // Give the MAIL FROM: header to the server + fputs ( $sp, "MAIL FROM: <$from" . "@" . "$serverName" . ">"."$CRLF"); + if ( $verbose ) eval("echo \"Client: MAIL FROM: $leftCarrot"."$from" . "@" . "$serverName" . "$rightCarrot\"; $vNL"); + + // Get output again + $output = fgets ( $sp, 2500 ); + // Check for multi-line positive output + if ( preg_match ( "/^...-/", $output ) ) { + $end = false; + while ( !$end ) { + // keep listening + $line = fgets ( $sp, 2500 ); + $output .= $line; + if ( preg_match ( "/^... /", $line ) ) { + // the last line of output shouldn't + // have a dash after the response code + $end = true; + } + } + } + if ( $verbose ) eval("echo \"Server: ".AddSlashes($output)."\"; $vNL"); + + // Give the RCPT TO: header for the email address we're testing + fputs ( $sp, "RCPT TO: <$email>"."$CRLF" ); + if ( $verbose ) eval("echo \"Client: RCPT TO: $leftCarrot"."$email"."$rightCarrot\"; $vNL"); + + // Get output again + // This will be the one we check for validity + $output = fgets ( $sp, 2500 ); + // Check for multi-line positive output + if ( preg_match ( "/^...-/", $output ) ) { + $end = false; + while ( !$end ) { + // keep listening + $line = fgets ( $sp, 2500 ); + $output .= $line; + if ( preg_match ( "/^... /", $line ) ) { + // the last line of output shouldn't + // have a dash after the response code + $end = true; + } + } + } + if ( $verbose ) eval("echo \"Server: ".AddSlashes($output)."\"; $vNL"); + + // test the last reply code from the mail server + // for the 250 (okay) response + if ( substr ( $output, 0, 3 ) == "250" ) { + + // set our true/false(ness) + // array item for testing + $return[0] = true; + $return[1] = $output; + if ( $verbose ) eval("echo \"Internal: Check for 250 ... Recipient OK\"; $vNL"); + + } else { + + // we didn't get a 250 + // may be a bogus address + if ( $verbose ) eval("echo \"Internal: Check for 250 ... Response did not begin with 250!\"; $vNL"); + // fill in 2nd array item with mail server's + // reply for user to test if they want + $return[0] = false; + $return[1] = $output; + + } + + // tell the mail server we're done + fputs ( $sp, "QUIT"."$CRLF" ); + if ( $verbose ) { + eval("echo \"Client: QUIT\"; $vNL"); + eval("echo \"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\"; $vNL $vNL"); + } + + // close the socket/file pointer + fclose ( $sp ); + + // If we got a good response back on RCPT TO, + // break here + // Otherwise, keep trying MX servers until we + // get a good response or run out of MX servers + // to try. + if ( $return[0] == true ) { + if ( $verbose ) { + eval("echo \"Internal: Recipient is OK - thanks, $mxhosts[$i]!\"; $vNL"); + eval("echo \"Internal: Stop checking MX hosts ...\"; $vNL"); + } + $bSuccess = true; + break; + } + + } else { + + // greetCode wasn't "220" + // we better skip this one and move on + if ( $verbose ) eval("echo \"Internal: SKIPPING $mxhosts[$i] -- never got 220 welcome\"; $vNL"); + // close out this connection + fclose ( $sp ); + + } // end of greetCode check + + } else { + // $sp socket pointer was false -- couldn't open it + if ( $verbose ) { + eval("echo \"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\"; $vNL"); + eval("echo \"Internal: could not open socket to $mxhosts[$i]!\"; $vNL"); + eval("echo \"fsockopen error $errno: $errstr\"; $vNL"); + eval("echo \"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\"; $vNL $vNL"); + } + $return[0] = false; + $return[1] = "fsockopen error $errno: $errstr"; + } // end of $sp check + + } // end for $mxhosts + + } // getmxrr test + else { + // getmxrr failed + if ( $verbose ) eval("echo \"Internal: No MX reverse records found for $domain\"; $vNL"); + $return[0] = false; + $return[1] = "554 No MX records found for $domain"; + } // end getmxrr test + + } // continue checkdnsrr test + else { + if ( $verbose ) eval("echo \"Internal: No DNS Reverse Record available!\"; $vNL"); + $return[0] = false; + $return[1] = "554 No DNS reverse record found for $domain"; + } // end checkdnsrr test + + } // end walking through each domain possibility + + } // end isValid + + // output elapsed time if Verbose + if ( $verbose ) { + list ( $msecStop, $secStop ) = explode ( " ", microtime() ); + $elapsedTime = (double)($secStop + $msecStop) - ($secStart + $msecStart); + $elapsedTime = number_format($elapsedTime,3); + eval("echo \"Internal: VERBOSE-MODE execution time: $elapsedTime seconds (silent mode somewhat faster)\"; $vNL"); + if ( $sapi_type != "cgi" ) echo "</pre>"; + } + + // return the array for the user to test against + return $return; + +} // END validateEmail-2.0 +?> diff --git a/modules/validatemail/validateEmailFormat.php b/modules/validatemail/validateEmailFormat.php new file mode 100644 index 00000000..aa03e62d --- /dev/null +++ b/modules/validatemail/validateEmailFormat.php @@ -0,0 +1,219 @@ +<?php +//////////////////////////////////////////////////////////////////////// +// +// validateEmailFormat.php - v 1.0 +// +// PHP translation of Email Regex Program (optimized) +// Derived from: +// Appendix B - Email Regex Program +// _Mastering Regular Expressions_ (First Edition, May 1997 revision) +// by Jeffrey E.F. Friedl +// Copyright 1997 O'Reilly & Associates +// ISBN: 1-56592-257-3 +// For more info on this title, see: +// http://www.oreilly.com/catalog/regex/ +// For original perl version, see: +// http://examples.oreilly.com/regex/ +// +// Follows RFC 822 about as close as is possible. +// http://www.faqs.org/rfcs/rfc822.html +// +// +// DESCRIPTION: +// bool validateEmailFormat ( string string ) +// +// Returns TRUE if the email address passed is in a valid format +// according to RFC 822, returns FALSE if email address passed +// is not in a valid format. +// +// EXAMPLES: +// Example #1: +// $email = "Jeffy <\"That Tall Guy\"@foo.com (blah blah blah)"; +// $isValid = validateEmailFormat($email); +// if($isValid) { +// ... // Yes, the above address is a valid format! +// } else { +// echo "sorry, that address isn't formatted properly."; +// } +// +// Example #2: +// $email = "foo@bar.co.il"; +// $isValid = validateEmailFormat($email); +// if($isValid) { +// ... +// } else { +// echo "sorry ..."; +// } +// +// Translated by Clay Loveless <clay@killersoft.com> on March 11, 2002 +// ... in hopes that the "here's how to check an e-mail address!" +// discussion can finally end. After all ... +// +// Friedl is the master -- Hail to the King, baby! +// +//////////////////////////////////////////////////////////////////////// +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// Hell, it might not even work for you. +// +// By using this code you agree to indemnify Clay Loveless, +// KillerSoft, and Crawlspace, Inc. from any liability that might +// arise from its use. +// +// Have fun! +// +//////////////////////////////////////////////////////////////////////// +function validateEmailFormat ( $email ) { + + // Some shortcuts for avoiding backslashitis + $esc = '\\\\'; $Period = '\.'; + $space = '\040'; $tab = '\t'; + $OpenBR = '\['; $CloseBR = '\]'; + $OpenParen = '\('; $CloseParen = '\)'; + $NonASCII = '\x80-\xff'; $ctrl = '\000-\037'; + $CRlist = '\n\015'; // note: this should really be only \015. + + // Items 19, 20, 21 -- see table on page 295 of 'Mastering Regular Expressions' + $qtext = "[^$esc$NonASCII$CRlist\"]"; // for within "..." + $dtext = "[^$esc$NonASCII$CRlist$OpenBR$CloseBR]"; // for within [...] + $quoted_pair = " $esc [^$NonASCII] "; // an escaped character + + // ********************************************* + // Items 22 and 23, comment. + // Impossible to do properly with a regex, I make do by allowing at most + // one level of nesting. + $ctext = " [^$esc$NonASCII$CRlist()] "; + + // $Cnested matches one non-nested comment. + // It is unrolled, with normal of $ctext, special of $quoted_pair. + $Cnested = ""; + $Cnested .= "$OpenParen"; // ( + $Cnested .= "$ctext*"; // normal* + $Cnested .= "(?: $quoted_pair $ctext* )*"; // (special normal*)* + $Cnested .= "$CloseParen"; // ) + + // $comment allows one level of nested parentheses + // It is unrolled, with normal of $ctext, special of ($quoted_pair|$Cnested) + $comment = ""; + $comment .= "$OpenParen"; // ( + $comment .= "$ctext*"; // normal* + $comment .= "(?:"; // ( + $comment .= "(?: $quoted_pair | $Cnested )"; // special + $comment .= "$ctext*"; // normal* + $comment .= ")*"; // )* + $comment .= "$CloseParen"; // ) + + // ********************************************* + // $X is optional whitespace/comments + $X = ""; + $X .= "[$space$tab]*"; // Nab whitespace + $X .= "(?: $comment [$space$tab]* )*"; // If comment found, allow more spaces + + + // Item 10: atom + $atom_char = "[^($space)<>\@,;:\".$esc$OpenBR$CloseBR$ctrl$NonASCII]"; + $atom = ""; + $atom .= "$atom_char+"; // some number of atom characters ... + $atom .= "(?!$atom_char)"; // ... not followed by something that + // could be part of an atom + + // Item 11: doublequoted string, unrolled. + $quoted_str = ""; + $quoted_str .= "\""; // " + $quoted_str .= "$qtext *"; // normal + $quoted_str .= "(?: $quoted_pair $qtext * )*"; // ( special normal* )* + $quoted_str .= "\""; // " + + + // Item 7: word is an atom or quoted string + $word = ""; + $word .= "(?:"; + $word .= "$atom"; // Atom + $word .= "|"; // or + $word .= "$quoted_str"; // Quoted string + $word .= ")"; + + // Item 12: domain-ref is just an atom + $domain_ref = $atom; + + // Item 13: domain-literal is like a quoted string, but [...] instead of "..." + $domain_lit = ""; + $domain_lit .= "$OpenBR"; // [ + $domain_lit .= "(?: $dtext | $quoted_pair )*"; // stuff + $domain_lit .= "$CloseBR"; // ] + + // Item 9: sub-domain is a domain-ref or a domain-literal + $sub_domain = ""; + $sub_domain .= "(?:"; + $sub_domain .= "$domain_ref"; + $sub_domain .= "|"; + $sub_domain .= "$domain_lit"; + $sub_domain .= ")"; + $sub_domain .= "$X"; // optional trailing comments + + // Item 6: domain is a list of subdomains separated by dots + $domain = ""; + $domain .= "$sub_domain"; + $domain .= "(?:"; + $domain .= "$Period $X $sub_domain"; + $domain .= ")*"; + + // Item 8: a route. A bunch of "@ $domain" separated by commas, followed by a colon. + $route = ""; + $route .= "\@ $X $domain"; + $route .= "(?: , $X \@ $X $domain )*"; // additional domains + $route .= ":"; + $route .= "$X"; // optional trailing comments + + // Item 5: local-part is a bunch of $word separated by periods + $local_part = ""; + $local_part .= "$word $X"; + $local_part .= "(?:"; + $local_part .= "$Period $X $word $X"; // additional words + $local_part .= ")*"; + + // Item 2: addr-spec is local@domain + $addr_spec = "$local_part \@ $X $domain"; + + // Item 4: route-addr is <route? addr-spec> + $route_addr = ""; + $route_addr .= "< $X"; + $route_addr .= "(?: $route )?"; // optional route + $route_addr .= "$addr_spec"; // address spec + $route_addr .= ">"; + + // Item 3: phrase........ + $phrase_ctrl = '\000-\010\012-\037'; // like ctrl, but without tab + + // Like atom-char, but without listing space, and uses phrase_ctrl. + // Since the class is negated, this matches the same as atom-char plus space and tab + $phrase_char = "[^()<>\@,;:\".$esc$OpenBR$CloseBR$NonASCII$phrase_ctrl]"; + + // We've worked it so that $word, $comment, and $quoted_str to not consume trailing $X + // because we take care of it manually. + $phrase = ""; + $phrase .= "$word"; // leading word + $phrase .= "$phrase_char *"; // "normal" atoms and/or spaces + $phrase .= "(?:"; + $phrase .= "(?: $comment | $quoted_str )"; // "special" comment or quoted string + $phrase .= "$phrase_char *"; // more "normal" + $phrase .= ")*"; + + // Item 1: mailbox is an addr_spec or a phrase/route_addr + $mailbox = ""; + $mailbox .= "$X"; // optional leading comment + $mailbox .= "(?:"; + $mailbox .= "$addr_spec"; // address + $mailbox .= "|"; // or + $mailbox .= "$phrase $route_addr"; // name and address + $mailbox .= ")"; + + // test it and return results + $isValid = preg_match("/^$mailbox$/xS",$email); + + return($isValid); +} // END validateEmailFormat +?> @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/playlist.php b/playlist.php index fd59a550..4f99293c 100644 --- a/playlist.php +++ b/playlist.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All Rights Reserved This program is free software; you can redistribute it and/or diff --git a/randomplay.php b/randomplay.php index 1fa9c900..e46cea07 100644 --- a/randomplay.php +++ b/randomplay.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or diff --git a/register.php b/register.php index 806f06bc..1034312d 100644 --- a/register.php +++ b/register.php @@ -1,7 +1,7 @@ <?php /* - Copyright (c) 2001 - 2005 Ampache.org + Copyright (c) 2001 - 2006 Ampache.org All rights reserved. This program is free software; you can redistribute it and/or @@ -30,6 +30,14 @@ $no_session = true; require_once ("modules/init.php"); +//Captcha + +define ("CAPTCHA_INVERSE, 1"); +include ("modules/captcha/captcha.php"); +require ("modules/validatemail/validateEmailFormat.php"); +require ("modules/validatemail/validateEmail.php"); + + /* Check Perms */ if (!conf('allow_public_registration')) { access_denied(); @@ -53,57 +61,84 @@ switch ($action) { // possibly by logging them in right then and there with their current info // and 'click here to login' would just be a link back to index.php if (conf('demo_mode')) { break; } + $captcha = captcha::check(); $accept_agreement = scrub_in($_REQUEST['accept_agreement']); $fullname = scrub_in($_REQUEST['fullname']); $username = scrub_in($_REQUEST['username']); $email = scrub_in($_REQUEST['email']); $pass1 = scrub_in($_REQUEST['password_1']); $pass2 = scrub_in($_REQUEST['password_2']); + + if(!isset ($captcha)){ + $GLOBALS['error']->add_error('captcha',_("Error Captcha Required")); + } + if (isset ($captcha)){ + if ($captcha) { + $msg="SUCCESS"; + } + else { + $GLOBALS['error']->add_error('captcha',_("Error Captcha Failed")); + } + } + if(conf('user_agreement')==true){ if(!$accept_agreement){ - echo("<center><b>You <u>must</u> accept the user agreement</b><br>"); - echo("Click <b><a href=\"javascript:history.back(1)\">here</a></b> to go back"); - break; + $GLOBALS['error']->add_error('user_agreement',_("You <U>must</U> accept the user agreement")); } } if(!$username){ - echo("<center><b>You did not enter a username</b><br>"); - echo("Click <b><a href=\"javascript:history.back(1)\">here</a></b> to go back"); - break; + $GLOBALS['error']->add_error('username',_("You did not enter a username")); } if(!$fullname){ - echo("<center><b>Please enter your full name</b><br>"); - echo("Click <b><a href=\"javascript:history.back(1)\">here</a></b> to go back"); - break; + $GLOBALS['error']->add_error('fullname',_("Please fill in your full name (Firstname Lastname)")); } - if(!good_email($email)){ - echo("<center><b>You must enter a valid email address</b><br>"); - echo("Click <b><a href=\"javascript:history.back(1)\">here</a></b> to go back"); - break; - } +//Check the mail for correct address formation. + + $attempt = 0; + $max_attempts = 3; + $response_code = ""; + + while ( $response_code == "" || strstr( $response_code, "fsockopen error" )) { + $validate_results = validateEmail( $email ); + $response_code = $validate_results[1]; + if($attempt == $max_attempts) break; + $attempt++; + } + + if ( $validate_results[0] ) { + $mmsg = "MAILOK"; + } + else { + $GLOBALS['error']->add_error('email',_("Error Email address not confirmed<br>$validate_results[1]")); + } +// End of mailcheck if(!$pass1){ - echo("<center><b>You must enter a password</b><br>"); - echo("Click <b><a href=\"javascript:history.back(1)\">here</a></b> to go back"); - break; + $GLOBALS['error']->add_error('password',_("You must enter a password")); } if ( $pass1 != $pass2 ) { - echo("<center><b>Your passwords do not match</b><br>"); - echo("Click <b><a href=\"javascript:history.back(1)\">here</a></b> to go back"); + $GLOBALS['error']->add_error('password',_("Your passwords do not match")); + } + + if($GLOBALS['error']->error_state){ + show_user_registration($values); break; } + $new_user = new_user("$username", "$fullname", "$email", "$pass1"); if(!$new_user){ - echo("<center><b>That username already exists</b><br>"); - echo("Click <b><a href=\"javascript:history.back(1)\">here</a></b> to go back"); + $GLOBALS['error']->add_error('duplicate_user',_("That username already exists")); + } + if($GLOBALS['error']->error_state){ + show_user_registration($values); break; } - break; +break; // This is the default action. case 'show_add_user': default: diff --git a/templates/show_user_registration.inc.php b/templates/show_user_registration.inc.php index b8ab67c6..4b637e58 100644 --- a/templates/show_user_registration.inc.php +++ b/templates/show_user_registration.inc.php @@ -46,16 +46,18 @@ $htmllang = str_replace("_","-",conf('lang')); <?php $action = scrub_in($_REQUEST['action']); -$fullname = scrub_in($_REQUEST['full_name']); +$fullname = scrub_in($_REQUEST['fullname']); $username = scrub_in($_REQUEST['username']); +$email = scrub_in($_REQUEST['email']); +/* $password = scrub_in($_REQUEST['password']); echo "$password"; - +*/ ?> <div align="center"> <form name="update_user" method="post" action="<?php echo conf('web_path'); ?>/register.php" enctype="multipart/form-data"> - <table class="border" width='600' cellpadding='0' cellspacing='0' border='0'> + <table class="border" width='700' cellpadding='0' cellspacing='0' border='0'> <tr class="table-header"> <td> <font size="2"><b><u>Ampache New User Registration</u></b></font> @@ -84,6 +86,7 @@ echo "$password"; <tr> <td align='center' height='35' valign='center'> <input type='checkbox' name='accept_agreement'> I Accept + <?php $GLOBALS['error']->print_error('user_agreement'); ?> </td> </tr> </table> @@ -104,13 +107,15 @@ echo "$password"; </tr> </table> <br /> - <table width='60%' cellpadding='0' cellspacing='0' border='0'> + <table width='99%' cellpadding='0' cellspacing='0' border='0'> <tr> <td align='right'> <?php echo _("Username"); ?>: </td> <td> - <font color='red'>*</font> <input type='text' name='username' id='username' /> + <font color='red'>*</font> <input type='text' name='username' id='username' value='<?php echo "$username"; ?>' /> + <?php $GLOBALS['error']->print_error('username'); ?> + <?php $GLOBALS['error']->print_error('duplicate_user'); ?> </td> </tr> <tr> @@ -118,7 +123,8 @@ echo "$password"; <?php echo _("Full Name"); ?>: </td> <td> - <font color='red'>*</font> <input type='text' name='fullname' id='fullname' /> + <font color='red'>*</font> <input type='text' name='fullname' id='fullname' value='<?php echo "$fullname"; ?>' /> + <?php $GLOBALS['error']->print_error('fullname'); ?> </td> </tr> <tr> @@ -126,7 +132,8 @@ echo "$password"; <?php echo _("E-mail"); ?>: </td> <td> - <font color='red'>*</font> <input type='text' name='email' id='email' /> + <font color='red'>*</font> <input type='text' name='email' id='email' value='<?php echo "$email"; ?>' /> + <?php $GLOBALS['error']->print_error('email'); ?> </td> </tr> <tr> @@ -135,6 +142,7 @@ echo "$password"; </td> <td> <font color='red'>*</font> <input type='password' name='password_1' id='password_1' /> + <?php $GLOBALS['error']->print_error('password'); ?> </td> </tr> <tr> @@ -146,12 +154,16 @@ echo "$password"; </td> </tr> <tr> - <td colspan='2' align='center' height='20'> + <?php echo captcha::form(); ?> + <?php $GLOBALS['error']->print_error('captcha'); ?> + </tr> + <tr> + <td colspan='2' bgcolor="<?php print conf('base_color2'); ?>" align='center' height='20'> <font color='red'>*</font>Required fields </td> </tr> <tr> - <td colspan='2' align='center' height='50'> + <td colspan='2' bgcolor="<?php print conf('base_color2'); ?>" align='center' height='50'> <input type="hidden" name="action" value="add_user" /> <input type='reset' name='clear_info' id='clear_info' value='Clear Info' /> <input type='submit' name='submit_registration' id='submit_registration' value='<?php echo _("Register User"); ?>' /> diff --git a/templates/show_users.inc b/templates/show_users.inc index dc43fb20..f91fbcc8 100644 --- a/templates/show_users.inc +++ b/templates/show_users.inc @@ -49,6 +49,12 @@ $admin_menu = "admin/"; </a> </td> <td align="center"> + <a href="<?php echo conf('web_path'); ?>/<?php echo $_SESSION['view_script']; ?>?action=<?php echo $_REQUEST['action']; ?>&keep_view=true&sort_type=last_seen&sort_order=0"> + <b><?php echo _("Registration Date"); ?></b> + </a> + </td> + + <td align="center"> <b><?php echo _("Edit"); ?></b> </td> <td align="center"> @@ -74,6 +80,9 @@ while ( $results = mysql_fetch_object($db_result) ) { $last_seen = date("m\/d\/Y - H:i",$user->last_seen); if (!$user->last_seen) { $last_seen = "Never"; } + $reg_date = date("m\/d\/Y - H:i",$user->reg_date); + if (!$user->reg_date) { $reg_date = "Unknown"; } + ?> <tr class="even"> <td> @@ -84,6 +93,10 @@ while ( $results = mysql_fetch_object($db_result) ) { <td align="center"> <?php echo $last_seen; ?> </td> + <td align="center"> + <?php echo $reg_date; ?> + </td> + <td> <a href="<?php echo conf('web_path'); ?>/admin/users.php?action=edit&user=<?php echo $user->username; ?>"> <?php echo _("Edit"); ?> |