Пример #1
0
     }
 }
 // Get the current file position
 if (!$error) {
     if (!$gzipmode) {
         $foffset = ftell($file);
     } else {
         $foffset = gztell($file);
     }
     if (!$foffset) {
         echo "<p class=\"error\">UNEXPECTED: Can't read the file pointer offset</p>\n";
         $error = true;
     }
 }
 // Print statistics
 skin_open();
 // echo ("<p class=\"centr\"><b>Statistics</b></p>\n");
 if (!$error) {
     $lines_this = $linenumber - $_REQUEST["start"];
     $lines_done = $linenumber - 1;
     $lines_togo = ' ? ';
     $lines_tota = ' ? ';
     $queries_this = $queries;
     $queries_done = $totalqueries;
     $queries_togo = ' ? ';
     $queries_tota = ' ? ';
     $bytes_this = $foffset - $_REQUEST["foffset"];
     $bytes_done = $foffset;
     $kbytes_this = round($bytes_this / 1024, 2);
     $kbytes_done = round($bytes_done / 1024, 2);
     $mbytes_this = round($kbytes_this / 1024, 2);
function db_script($db_name, $filename, $verbose = true)
{
    $db_server = HEURIST_DBSERVER_NAME;
    $db_username = ADMIN_DBUSERNAME;
    $db_password = ADMIN_DBUSERPSWD;
    // Connection charset should be the same as the dump file charset (utf8, latin1, cp1251, koi8r etc.)
    // See http://dev.mysql.com/doc/refman/5.0/en/charset-charsets.html for the full list
    // Change this if you have problems with non-latin letters
    $db_connection_charset = 'utf8';
    // OPTIONAL SETTINGS
    //$filename           = '';     // Specify the dump filename to suppress the file selection dialog
    $ajax = true;
    // AJAX mode: import will be done without refreshing the website
    $linespersession = 3000;
    // Lines to be executed per one import session
    $delaypersession = 0;
    // You can specify a sleep time in milliseconds after each session
    // Works only if JavaScript is activated. Use to reduce server overrun
    // CSV related settings (only if you use a CSV dump)
    $csv_insert_table = '';
    // Destination table for CSV files
    $csv_preempty_table = false;
    // true: delete all entries from table specified in $csv_insert_table before processing
    $csv_delimiter = ',';
    // Field delimiter in CSV file
    $csv_add_quotes = true;
    // If your CSV data already have quotes around each field set it to false
    $csv_add_slashes = true;
    // If your CSV data already have slashes in front of ' and " set it to false
    // Allowed comment markers: lines starting with these strings will be ignored by BigDump
    $comment[] = '#';
    // Standard comment lines are dropped by default
    $comment[] = '-- ';
    $comment[] = 'DELIMITER';
    // Ignore DELIMITER switch as it's not a valid SQL statement
    // $comment[]='---';                  // Uncomment this line if using proprietary dump created by outdated mysqldump
    // $comment[]='CREATE DATABASE';      // Uncomment this line if your dump contains create database queries in order to ignore them
    // $comment[]='/*!';                     // Or add your own string to leave out other proprietary things
    // Pre-queries: SQL queries to be executed at the beginning of each import session
    // $pre_query[]='SET foreign_key_checks = 0';
    // $pre_query[]='Add additional queries if you want here';
    // Default query delimiter: this character at the line end tells Bigdump where a SQL statement ends
    // Can be changed by DELIMITER statement in the dump file (normally used when defining procedures/functions)
    $delimiter = ';';
    // String quotes character
    $string_quotes = '\'';
    // Change to '"' if your dump file uses double qoutes for strings
    // How many lines may be considered to be one query (except text lines)
    $max_query_lines = 300;
    // Where to put the upload files into (default: bigdump folder)
    $upload_dir = dirname(__FILE__);
    // *******************************************************************************************
    // If not familiar with PHP please don't change anything below this line
    // *******************************************************************************************
    if (!$verbose || $ajax) {
        ob_start();
    }
    @ini_set('auto_detect_line_endings', true);
    @set_time_limit(0);
    if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) {
        @date_default_timezone_set(@date_default_timezone_get());
    }
    // Clean and strip anything we don't want from user's input [0.27b]
    $error = false;
    $file = false;
    // Check PHP version
    if (!$error && !function_exists('version_compare')) {
        echo "<p class=\"error\">PHP version 4.1.0 is required for db script read to proceed. You have PHP " . phpversion() . " installed. Sorry!</p>\n";
        $error = true;
    }
    // Check if mysql extension is available
    if (!$error && !function_exists('mysql_connect')) {
        echo "<p class=\"error\">There is no mySQL extension available in your PHP installation. Sorry!</p>\n";
        $error = true;
    }
    do_action('script_runs');
    // Connect to the database, set charset and execute pre-queries
    if (!$error && !TESTMODE) {
        $dbconnection = @mysql_connect($db_server, $db_username, $db_password);
        if ($dbconnection) {
            $db = mysql_select_db($db_name);
        }
        if (!$dbconnection || !$db) {
            echo "<p class=\"error\">Database connection failed due to " . mysql_error() . "</p>\n";
            echo "<p>Edit the database settings in your configuration file, or contact your system administrator.</p>\n";
            $error = true;
        }
        if (!$error && $db_connection_charset !== '') {
            @mysql_query("SET NAMES {$db_connection_charset}", $dbconnection);
        }
        if (!$error && isset($pre_query) && sizeof($pre_query) > 0) {
            reset($pre_query);
            foreach ($pre_query as $pre_query_value) {
                if (!@mysql_query($pre_query_value, $dbconnection)) {
                    echo "<p class=\"error\">Error with pre-query.</p>\n";
                    echo "<p>Query: " . trim(nl2br(htmlentities($pre_query_value))) . "</p>\n";
                    echo "<p>MySQL: " . mysql_error() . "</p>\n";
                    $error = true;
                    break;
                }
            }
        }
    } else {
        $dbconnection = false;
    }
    do_action('database_connected');
    // Single file mode
    if (!$error && !isset($_REQUEST["fn"]) && $filename != "") {
        //    echo ("<p><a href=\"".$_SERVER["PHP_SELF"]."?start=1&amp;fn=".urlencode($filename)."&amp;foffset=0&amp;totalqueries=0\">Start Import</a> from $filename into $db_name at $db_server</p>\n");
        $_REQUEST["start"] = "1";
        $_REQUEST["fn"] = $filename;
        $_REQUEST["foffset"] = 0;
        $_REQUEST["totalqueries"] = 0;
        //$filename = "";
    }
    // Open the file
    if (!$error && isset($_REQUEST["start"])) {
        // Set current filename ($filename overrides $_REQUEST["fn"] if set)
        if ($filename != "") {
            $curfilename = $filename;
        } else {
            if (isset($_REQUEST["fn"])) {
                $curfilename = urldecode($_REQUEST["fn"]);
            } else {
                $curfilename = "";
            }
        }
        //DEBUG error_log($curfilename);
        // Recognize GZip filename
        $gzipmode = false;
        if (!$gzipmode && !($file = @fopen($curfilename, "r")) || $gzipmode && !($file = @gzopen($curfilename, "r"))) {
            echo "<p class=\"error\">Can't open " . $curfilename . " for import</p>\n";
            echo "<p>Please, check that your script file name contains only alphanumerical characters, and rename it accordingly, for example: {$curfilename}." . "<br>Or, specify \$filename in bigdump.php with the full filename. " . "<br>Or, you have to upload the {$curfilename} to the server first.</p>\n";
            $error = true;
        } else {
            if (!$gzipmode && @fseek($file, 0, SEEK_END) == 0 || $gzipmode && @gzseek($file, 0) == 0) {
                if (!$gzipmode) {
                    $filesize = ftell($file);
                } else {
                    $filesize = gztell($file);
                }
                // Always zero, ignore
            } else {
                echo "<p class=\"error\">I can't seek into {$curfilename}</p>\n";
                $error = true;
            }
        }
        // Stop if csv file is used, but $csv_insert_table is not set
        if (!$error && $csv_insert_table == "" && preg_match("/(\\.csv)\$/i", $curfilename)) {
            echo "<p class=\"error\">You have to specify \$csv_insert_table when using a CSV file. </p>\n";
            $error = true;
        }
    }
    // *******************************************************************************************
    // START IMPORT SESSION HERE
    // *******************************************************************************************
    if (!$error && isset($_REQUEST["start"]) && isset($_REQUEST["foffset"]) && preg_match("/(\\.(sql|gz|csv))\$/i", $curfilename)) {
        do_action('session_start');
        // Check start and foffset are numeric values
        if (!is_numeric($_REQUEST["start"]) || !is_numeric($_REQUEST["foffset"])) {
            echo "<p class=\"error\">UNEXPECTED: Non-numeric values for start and foffset</p>\n";
            $error = true;
        } else {
            $_REQUEST["start"] = floor($_REQUEST["start"]);
            $_REQUEST["foffset"] = floor($_REQUEST["foffset"]);
        }
        // Set the current delimiter if defined
        if (isset($_REQUEST["delimiter"])) {
            $delimiter = $_REQUEST["delimiter"];
        }
        // Empty CSV table if requested
        if (!$error && $_REQUEST["start"] == 1 && $csv_insert_table != "" && $csv_preempty_table) {
            $query = "DELETE FROM `{$csv_insert_table}`";
            if (!TESTMODE && !mysql_query(trim($query), $dbconnection)) {
                echo "<p class=\"error\">Error when deleting entries from {$csv_insert_table}.</p>\n";
                echo "<p>Query: " . trim(nl2br(htmlentities($query))) . "</p>\n";
                echo "<p>MySQL: " . mysql_error() . "</p>\n";
                $error = true;
            }
        }
        // Print start message
        if (!$error && TESTMODE) {
            skin_open();
            echo "<p class=\"centr\">TEST MODE ENABLED</p>\n";
            echo "<p class=\"centr\">Processing file: <b>" . $curfilename . "</b></p>\n";
            echo "<p class=\"smlcentr\">Starting from line: " . $_REQUEST["start"] . "</p>\n";
            skin_close();
        }
        // Check $_REQUEST["foffset"] upon $filesize (can't do it on gzipped files)
        if (!$error && !$gzipmode && $_REQUEST["foffset"] > $filesize) {
            echo "<p class=\"error\">UNEXPECTED: Can't set file pointer behind the end of file</p>\n";
            $error = true;
        }
        // Set file pointer to $_REQUEST["foffset"]
        if (!$error && (!$gzipmode && fseek($file, $_REQUEST["foffset"]) != 0 || $gzipmode && gzseek($file, $_REQUEST["foffset"]) != 0)) {
            echo "<p class=\"error\">UNEXPECTED: Can't set file pointer to offset: " . $_REQUEST["foffset"] . "</p>\n";
            $error = true;
        }
        // Start processing queries from $file
        if (!$error) {
            $query = "";
            $queries = 0;
            $totalqueries = $_REQUEST["totalqueries"];
            $linenumber = $_REQUEST["start"];
            $querylines = 0;
            $inparents = false;
            // Stay processing as long as the $linespersession is not reached or the query is still incomplete
            while ($linenumber < $_REQUEST["start"] + $linespersession || $query != "") {
                // Read the whole next line
                $dumpline = "";
                while (!feof($file) && substr($dumpline, -1) != "\n" && substr($dumpline, -1) != "\r") {
                    if (!$gzipmode) {
                        $dumpline .= fgets($file, DATA_CHUNK_LENGTH);
                    } else {
                        $dumpline .= gzgets($file, DATA_CHUNK_LENGTH);
                    }
                }
                if ($dumpline === "") {
                    break;
                }
                // Remove UTF8 Byte Order Mark at the file beginning if any
                if ($_REQUEST["foffset"] == 0) {
                    $dumpline = preg_replace('|^\\xEF\\xBB\\xBF|', '', $dumpline);
                }
                // Create an SQL query from CSV line
                if ($csv_insert_table != "" && preg_match("/(\\.csv)\$/i", $curfilename)) {
                    if ($csv_add_slashes) {
                        $dumpline = addslashes($dumpline);
                    }
                    $dumpline = explode($csv_delimiter, $dumpline);
                    if ($csv_add_quotes) {
                        $dumpline = "'" . implode("','", $dumpline) . "'";
                    } else {
                        $dumpline = implode(",", $dumpline);
                    }
                    $dumpline = 'INSERT INTO ' . $csv_insert_table . ' VALUES (' . $dumpline . ');';
                }
                // Handle DOS and Mac encoded linebreaks (I don't know if it really works on Win32 or Mac Servers)
                $dumpline = str_replace("\r\n", "\n", $dumpline);
                $dumpline = str_replace("\r", "\n", $dumpline);
                // DIAGNOSTIC
                // echo ("<p>Line $linenumber: $dumpline</p>\n");
                // Recognize delimiter statement
                if (!$inparents && strpos($dumpline, "DELIMITER ") === 0) {
                    $delimiter = str_replace("DELIMITER ", "", trim($dumpline));
                }
                // Skip comments and blank lines only if NOT in parents
                if (!$inparents) {
                    $skipline = false;
                    reset($comment);
                    foreach ($comment as $comment_value) {
                        // DIAGNOSTIC
                        //          echo ($comment_value);
                        if (trim($dumpline) == "" || strpos(trim($dumpline), $comment_value) === 0) {
                            $skipline = true;
                            break;
                        }
                    }
                    if ($skipline) {
                        $linenumber++;
                        // DIAGNOSTIC
                        // echo ("<p>Comment line skipped</p>\n");
                        continue;
                    }
                }
                // Remove double back-slashes from the dumpline prior to count the quotes ('\\' can only be within strings)
                $dumpline_deslashed = str_replace("\\\\", "", $dumpline);
                // Count ' and \' (or " and \") in the dumpline to avoid query break within a text field ending by $delimiter
                $parents = substr_count($dumpline_deslashed, $string_quotes) - substr_count($dumpline_deslashed, "\\{$string_quotes}");
                if ($parents % 2 != 0) {
                    $inparents = !$inparents;
                }
                // Add the line to query
                $query .= $dumpline;
                // Don't count the line if in parents (text fields may include unlimited linebreaks)
                if (!$inparents) {
                    $querylines++;
                }
                // Stop if query contains more lines as defined by $max_query_lines
                if ($querylines > $max_query_lines) {
                    echo "<p class=\"error\">Stopped at the line {$linenumber}. </p>";
                    echo "<p>At this place the current query includes more than " . $max_query_lines . " dump lines. That can happen if your dump file was ";
                    echo "created by some tool which doesn't place a semicolon followed by a linebreak at the end of each query, or if your dump contains ";
                    echo "extended inserts or very long procedure definitions.</p>\n";
                    $error = true;
                    break;
                }
                // Execute query if end of query detected ($delimiter as last character) AND NOT in parents
                // DIAGNOSTIC
                // echo ("<p>Regex: ".'/'.preg_quote($delimiter).'$/'."</p>\n");
                // echo ("<p>In Parents: ".($inparents?"true":"false")."</p>\n");
                // echo ("<p>Line: $dumpline</p>\n");
                if ((preg_match('/' . preg_quote($delimiter, '/') . '$/', trim($dumpline)) || $delimiter == '') && !$inparents) {
                    // Cut off delimiter of the end of the query
                    $query = substr(trim($query), 0, -1 * strlen($delimiter));
                    // DIAGNOSTIC
                    // echo ("<p>Query: ".trim(nl2br(htmlentities($query)))."</p>\n");
                    if (!TESTMODE && !mysql_query($query, $dbconnection)) {
                        echo "<p class=\"error\">Error at the line {$linenumber}: " . trim($dumpline) . "</p>\n";
                        echo "<p>Query: " . trim(nl2br(htmlentities($query))) . "</p>\n";
                        echo "<p>MySQL: " . mysql_error() . "</p>\n";
                        $error = true;
                        break;
                    }
                    $totalqueries++;
                    $queries++;
                    $query = "";
                    $querylines = 0;
                }
                $linenumber++;
            }
        }
        // Get the current file position
        if (!$error) {
            if (!$gzipmode) {
                $foffset = ftell($file);
            } else {
                $foffset = gztell($file);
            }
            if (!$foffset) {
                echo "<p class=\"error\">UNEXPECTED: Can't read the file pointer offset</p>\n";
                $error = true;
            }
        }
        // Print statistics
        if (TESTMODE) {
            skin_open();
            // echo ("<p class=\"centr\"><b>Statistics</b></p>\n");
            if (!$error) {
                $lines_this = $linenumber - $_REQUEST["start"];
                $lines_done = $linenumber - 1;
                $lines_togo = ' ? ';
                $lines_tota = ' ? ';
                $queries_this = $queries;
                $queries_done = $totalqueries;
                $queries_togo = ' ? ';
                $queries_tota = ' ? ';
                $bytes_this = $foffset - $_REQUEST["foffset"];
                $bytes_done = $foffset;
                $kbytes_this = round($bytes_this / 1024, 2);
                $kbytes_done = round($bytes_done / 1024, 2);
                $mbytes_this = round($kbytes_this / 1024, 2);
                $mbytes_done = round($kbytes_done / 1024, 2);
                if (!$gzipmode) {
                    $bytes_togo = $filesize - $foffset;
                    $bytes_tota = $filesize;
                    $kbytes_togo = round($bytes_togo / 1024, 2);
                    $kbytes_tota = round($bytes_tota / 1024, 2);
                    $mbytes_togo = round($kbytes_togo / 1024, 2);
                    $mbytes_tota = round($kbytes_tota / 1024, 2);
                    $pct_this = ceil($bytes_this / $filesize * 100);
                    $pct_done = ceil($foffset / $filesize * 100);
                    $pct_togo = 100 - $pct_done;
                    $pct_tota = 100;
                    if ($bytes_togo == 0) {
                        $lines_togo = '0';
                        $lines_tota = $linenumber - 1;
                        $queries_togo = '0';
                        $queries_tota = $totalqueries;
                    }
                    $pct_bar = "<div style=\"height:15px;width:{$pct_done}%;background-color:#000080;margin:0px;\"></div>";
                } else {
                    $bytes_togo = ' ? ';
                    $bytes_tota = ' ? ';
                    $kbytes_togo = ' ? ';
                    $kbytes_tota = ' ? ';
                    $mbytes_togo = ' ? ';
                    $mbytes_tota = ' ? ';
                    $pct_this = ' ? ';
                    $pct_done = ' ? ';
                    $pct_togo = ' ? ';
                    $pct_tota = 100;
                    $pct_bar = str_replace(' ', '&nbsp;', '<tt>[         Not available for gzipped files          ]</tt>');
                }
                echo "\n    <center>\n    <table width=\"520\" border=\"0\" cellpadding=\"3\" cellspacing=\"1\">\n    <tr><th class=\"bg4\"> </th><th class=\"bg4\">Session</th><th class=\"bg4\">Done</th><th class=\"bg4\">To go</th><th class=\"bg4\">Total</th></tr>\n    <tr><th class=\"bg4\">Lines</th><td class=\"bg3\">{$lines_this}</td><td class=\"bg3\">{$lines_done}</td><td class=\"bg3\">{$lines_togo}</td><td class=\"bg3\">{$lines_tota}</td></tr>\n    <tr><th class=\"bg4\">Queries</th><td class=\"bg3\">{$queries_this}</td><td class=\"bg3\">{$queries_done}</td><td class=\"bg3\">{$queries_togo}</td><td class=\"bg3\">{$queries_tota}</td></tr>\n    <tr><th class=\"bg4\">Bytes</th><td class=\"bg3\">{$bytes_this}</td><td class=\"bg3\">{$bytes_done}</td><td class=\"bg3\">{$bytes_togo}</td><td class=\"bg3\">{$bytes_tota}</td></tr>\n    <tr><th class=\"bg4\">KB</th><td class=\"bg3\">{$kbytes_this}</td><td class=\"bg3\">{$kbytes_done}</td><td class=\"bg3\">{$kbytes_togo}</td><td class=\"bg3\">{$kbytes_tota}</td></tr>\n    <tr><th class=\"bg4\">MB</th><td class=\"bg3\">{$mbytes_this}</td><td class=\"bg3\">{$mbytes_done}</td><td class=\"bg3\">{$mbytes_togo}</td><td class=\"bg3\">{$mbytes_tota}</td></tr>\n    <tr><th class=\"bg4\">%</th><td class=\"bg3\">{$pct_this}</td><td class=\"bg3\">{$pct_done}</td><td class=\"bg3\">{$pct_togo}</td><td class=\"bg3\">{$pct_tota}</td></tr>\n    <tr><th class=\"bg4\">% bar</th><td class=\"bgpctbar\" colspan=\"4\">{$pct_bar}</td></tr>\n    </table>\n    </center>\n    \n";
                // Finish message and restart the script
                if ($linenumber < $_REQUEST["start"] + $linespersession) {
                    echo "<p class=\"successcentr\">Congratulations: End of file reached, assuming OK</p>\n";
                    do_action('script_finished');
                    $error = true;
                    // This is a semi-error telling the script is finished
                } else {
                    if ($delaypersession != 0) {
                        echo "<p class=\"centr\">Now I'm <b>waiting {$delaypersession} milliseconds</b> before starting next session...</p>\n";
                    }
                    if (!$ajax) {
                        echo "<script language=\"JavaScript\" type=\"text/javascript\">window.setTimeout('location.href=\"" . $_SERVER["PHP_SELF"] . "?start={$linenumber}&fn=" . urlencode($curfilename) . "&foffset={$foffset}&totalqueries={$totalqueries}&delimiter=" . urlencode($delimiter) . "\";',500+{$delaypersession});</script>\n";
                    }
                    echo "<noscript>\n";
                    echo "<p class=\"centr\"><a href=\"" . $_SERVER["PHP_SELF"] . "?start={$linenumber}&amp;fn=" . urlencode($curfilename) . "&amp;foffset={$foffset}&amp;totalqueries={$totalqueries}&amp;delimiter=" . urlencode($delimiter) . "\">Continue from the line {$linenumber}</a> (Enable JavaScript to do it automatically)</p>\n";
                    echo "</noscript>\n";
                    echo "<p class=\"centr\">Press <b><a href=\"" . $_SERVER["PHP_SELF"] . "\">STOP</a></b> to abort the import <b>OR WAIT!</b></p>\n";
                }
            } else {
                echo "<p class=\"error\">Stopped on error</p>\n";
            }
            skin_close();
        }
        //end TESTMODE statistics
    }
    if ($error && TESTMODE) {
        echo "<p class=\"centr\"><a href=\"" . $_SERVER["PHP_SELF"] . "\">Start from the beginning</a> (DROP the old tables before restarting)</p>\n";
    }
    if ($dbconnection) {
        mysql_close($dbconnection);
    }
    if ($file && !$gzipmode) {
        fclose($file);
    } else {
        if ($file && $gzipmode) {
            gzclose($file);
        }
    }
    // If error or finished put out the whole output from above and stop
    if ($error && $verbose) {
        $out1 = ob_get_contents();
        ob_end_clean();
        echo $out1;
    } else {
        ob_clean();
    }
    // Anyway put out the output from above
    //ob_flush();
    return !$error;
}