#!/usr/bin/php4 -q
<?php
/*
 * Copyright (c)  2005 Emiliano Gabrielli
 * AlberT@SuperAlberT.it - http://www.SuperAlberT.it
 *
 * An up to date copy of this script may be retrived at
 * http://www.SuperAlberT.it/download/command_line_scripts/phpBB/
 *
 * This work is licensed under the Creative Commons Attribution-ShareAlike 
 * License. To view a copy of this license, visit 
 * http://creativecommons.org/licenses/by-sa/2.0/
 * or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, 
 * California 94305, USA.
 *
 * $Id: phpbb_mass_user_create,v 1.3 2005/08/04 10:03:24 albert Exp $
 */

error_reporting(E_ALL);
if (
php_sapi_name()!='cli')
    die(
"This script needs php-cli in order to correctly work!\n");

/************************ CONFIGURATION *************************************/

define('SCRIPT_NAME',  'phpbb_mass_user_create');
define('VERSION',      0.2);
#define('DEBUG',        TRUE);

/************************** FUNCTIONS ***************************************/

function p_debug($str)
{
    if (!
defined('DEBUG') || DEBUG!==TRUE) {
        return 
FALSE;
    }
    
fwrite(STDERR"DEBUG: $str\n") ;

    return 
TRUE;
}

function 
p_error($str)
{
    
fwrite(STDERR"ERROR: $str\n");
}

function 
p_fatal($str)
{
    
fwrite(STDERR"FATAL: $str\n");
    exit;
}

function 
p_help()
{
    
fwrite(STDERR, <<<EOT

USE:
    To be invoked from command line.
    
{$_SERVER['argv'][0]} [options] -c conf_file
    
    The script gets user/password couples from standard input and creates phpBB
    users and groups.

OPTIONS:
    -d data_delim   Optional, input data delimiter. Defaults to ':'
    -g groups       A list of groups the users being created had to belong to,
                    you are required to provide a group at least.
    -D group_delim  Optional, input data delimiter.
                    Defaults to the same value of "group_delim"
    -c conf_file    Path to phpBB configuration file (config.php)
    -l lang         phpBB user's language. Defaults to "english"
    -T timezone     phpBB user's timezone (must be an offset from GMT), 
                    1.00, -2.00, -4 are allowed values. Defaults to "0.00"
    -h              Print this message and exit
    -V              Print version and exit

EOT
          );
}

function 
create_phpbb_user($data) {
    global 
$db;
    
    
extract($data);
    
extract($db['tables']);
    
$dbh $db['id'];
    
    
/*
     * Check if the user is already present
     */
    
$sql "SELECT `user_id` FROM `$u` WHERE `username` = '$user'";
    
$res mysql_query($sql$dbh) or p_fatal(mysql_error());
    if (
mysql_num_rows($res)) {
        
p_error("Username '$user' already present. Skipping");
        return 
FALSE;
    }
    
    
/*
     * First we have to create the user...
     */
    
$sql "SELECT MAX(`user_id`) FROM `$u`";
    
$res mysql_query($sql$dbh) or p_fatal(mysql_error());
    
$umax mysql_result($res00) or p_fatal(mysql_error());
    
p_debug("Max user_id in table '$u' is '$umax'");
    ++
$umax;
    
$sql =
<<<EOSQL
INSERT INTO `$u
    (`user_id`, `user_active`, `username`, `user_password`, `user_timezone`, `user_lang`) 
VALUES 
    (
$umax, 1, '$user', MD5('$pwd'), '$tz', '$lang');
EOSQL;

    
mysql_query($sql$dbh) or p_fatal(mysql_error());

    
    
/*
     * ... now we have to associate the user to the groups
     */
    
$sql="INSERT INTO `$u_g` (`group_id`, `user_id`, `user_pending`) VALUES ";
    foreach (
$groups as $k=>$g) {
        
$values[] = "($g$umax, 0)";
    }
    
$sql .= implode(','$values);
    
mysql_query($sql$dbh) or p_fatal(mysql_error());
    
    return 
TRUE;
}

function 
create_phpbb_group($group) {
    global 
$db;
    
    
extract($db['tables']);
    
$dbh $db['id'];
    
$sql "SELECT `group_id` FROM `$g` WHERE `group_name` = '$group'";
    
$res mysql_query($sql$dbh) or p_fatal(mysql_error());
    if (
mysql_num_rows($res)) {
        return (int)
mysql_result($res00);
    }

    
/*
     * we have to create a new group
     */
    
$sql "SELECT MAX(`group_id`) FROM `$g`";
    
$res mysql_query($sql$dbh) or p_fatal(mysql_error());
    
$gmax mysql_result($res00) or p_fatal(mysql_error());
    
p_debug("Max group_id in table '$g' is '$gmax'");
    ++
$gmax;
    
//FIXME: we have to take in account that if we create a new group
    // the user has to supply a group moderator too
    
$sql =
<<<EOSQL
INSERT INTO `$g
    (`group_id`, `group_type`, `group_name`, `group_description`, `group_moderator`, `group_single_user`) 
VALUES 
    ('
$gmax',    '1',          '$group',     '',                  '0',               '1');
EOSQL;
    
    
mysql_query($sql$dbh) or p_fatal(mysql_error());
    
p_debug("Group '$group' does not exists.. created with group_id='$gmax'");

    return (int)
$gmax;
}

/************************** MAIN PROGRAM ************************************/

/*
 * parse command line options
 */
$opts getopt('Vhg:d:D:c:l:T:');
foreach (
$opts as $k => $v) {
    if (
FALSE!==$offset=array_search("-$k"$_SERVER['argv'])) {
        
array_splice($_SERVER['argv'], $offset1);
        --
$_SERVER['argc']; 
    }
    if (
FALSE!==$offset=array_search($v$_SERVER['argv'])) {
        
array_splice($_SERVER['argv'], $offset1);
        --
$_SERVER['argc']; 
    }
}
/*
 * check options and arguments "Vhd:g:D:"
 */
if (array_key_exists('V'$opts)) {
    
fwrite(STDOUTSCRIPT_NAME.' v. '.VERSION."\n");
    exit;
}
if (
array_key_exists('h'$opts)) {
    
p_help();
    exit;
}
if ((
array_key_exists('g'$opts) && empty($opts['g'])) || 
    (
array_key_exists('d'$opts) && empty($opts['d'])) || 
    (
array_key_exists('D'$opts) && empty($opts['D'])) || 
    (
array_key_exists('l'$opts) && empty($opts['l'])) || 
    (
array_key_exists('T'$opts) && empty($opts['T'])) || 
    (!
array_key_exists('c'$opts) || empty($opts['c'])) ) {
    
p_help();
    exit;
}
$udata['lang'] = (array_key_exists('l'$opts)) ? $opts['l'] : 'english' ;
$udata['tz']   = (array_key_exists('T'$opts)) ? is_numeric($opts['T']) : '0.00' ;
$delim         = (array_key_exists('d'$opts)) ? $opts['d'] : ':' ;
$g_delim       = (array_key_exists('D'$opts)) ? $opts['D'] : $delim ;
if (!
array_key_exists('g'$opts)) {
    
p_help();
    
p_fatal("You have to provide a group name at least.");
}
$groups explode($g_delimtrim($opts['g']));
if ( !
count($groups) ) {
    
p_fatal("\tLine ".++$i." in STDIN does not contain any occurrence of delimiter '$g_delim'. ");
}    
p_debug("Given groups: '".implode("','"$groups)."'");

if (!
is_readable($opts['c'])) {
    
p_fatal("phpBB configuration file ('{$opts['c']}') is unreadable!");
}
include_once 
$opts['c'];
if (!
defined('PHPBB_INSTALLED') || !PHPBB_INSTALLED) {
    
p_fatal("phpBB seems to be not correctly installed!");
}
/*
 * Now we should have the following data:
 *  $dbhost, $dbname, $dbuser, $dbpasswd, $table_prefix
 */
  
$db['id'] = mysql_connect($dbhost$dbuser$dbpasswd);
mysql_select_db($dbname) or p_fatal(mysql_error());
$db['tables']['u']   = "{$table_prefix}users";
$db['tables']['g']   = "{$table_prefix}groups";
$db['tables']['u_g'] = "{$table_prefix}user_group";

/*
 * Check if given groups allready exist, otherwise create them
 */
foreach ($groups as $k=>$g) {
    
$udata['groups'][] = create_phpbb_group($g);
}

/*
 * For every line in STDIN check if it is a valid user/passwd couple 
 * and then add the user to the DB structure
 */
$i $tot 0;
while (
FALSE!==$row=fgets(STDIN)) {
    ++
$i;
    if ( 
FALSE===strpos($row$delim) ) {
        
p_fatal("\tLine $i in STDIN does not contain any occurrence of delimiter '$delim'. ");
    }    
    list( 
$udata['user'], $udata['pwd']) = array_values(explode($delimtrim($row)));

    
$tot+=create_phpbb_user($udata);
}
echo 
"Done. $tot users created.\n";

?>