function executeScript($name, $callback = null)
{
global $data;
// This whole function isn't very encapsulated, but hey...
$conn = $data->conn->_connectionID;
if (!is_uploaded_file($_FILES[$name]['tmp_name'])) {
return false;
}
$fd = fopen($_FILES[$name]['tmp_name'], 'r');
if (!$fd) {
return false;
}
// Build up each SQL statement, they can be multiline
$query_buf = null;
$query_start = 0;
$in_quote = 0;
$in_xcomment = 0;
$bslash_count = 0;
$dol_quote = null;
$paren_level = 0;
$len = 0;
$i = 0;
$prevlen = 0;
$thislen = 0;
$lineno = 0;
// Loop over each line in the file
while (!feof($fd)) {
$line = fgets($fd);
$lineno++;
// Nothing left on line? Then ignore...
if (trim($line) == '') {
continue;
}
$len = strlen($line);
$query_start = 0;
/*
* Parse line, looking for command separators.
*
* The current character is at line[i], the prior character at line[i
* - prevlen], the next character at line[i + thislen].
*/
$prevlen = 0;
$thislen = $len > 0 ? 1 : 0;
for ($i = 0; $i < $len; $this->advance_1($i, $prevlen, $thislen)) {
/* was the previous character a backslash? */
if ($i > 0 && substr($line, $i - $prevlen, 1) == '\\') {
$bslash_count++;
} else {
$bslash_count = 0;
}
/*
* It is important to place the in_* test routines before the
* in_* detection routines. i.e. we have to test if we are in
* a quote before testing for comments.
*/
/* in quote? */
if ($in_quote !== 0) {
/*
* end of quote if matching non-backslashed character.
* backslashes don't count for double quotes, though.
*/
if (substr($line, $i, 1) == $in_quote && ($bslash_count % 2 == 0 || $in_quote == '"')) {
$in_quote = 0;
}
} else {
if ($dol_quote) {
if (strncmp(substr($line, $i), $dol_quote, strlen($dol_quote)) == 0) {
$this->advance_1($i, $prevlen, $thislen);
while (substr($line, $i, 1) != '$') {
$this->advance_1($i, $prevlen, $thislen);
}
$dol_quote = null;
}
} else {
if (substr($line, $i, 2) == '/*') {
$in_xcomment++;
if ($in_xcomment == 1) {
$this->advance_1($i, $prevlen, $thislen);
}
} else {
if ($in_xcomment) {
if (substr($line, $i, 2) == '*/' && !--$in_xcomment) {
$this->advance_1($i, $prevlen, $thislen);
}
} else {
if (substr($line, $i, 1) == '\'' || substr($line, $i, 1) == '"') {
$in_quote = substr($line, $i, 1);
} else {
if (!$dol_quote && $this->valid_dolquote(substr($line, $i))) {
$dol_end = strpos(substr($line, $i + 1), '$');
$dol_quote = substr($line, $i, $dol_end + 1);
$this->advance_1($i, $prevlen, $thislen);
while (substr($line, $i, 1) != '$') {
$this->advance_1($i, $prevlen, $thislen);
}
} else {
if (substr($line, $i, 2) == '--') {
$line = substr($line, 0, $i);
/* remove comment */
break;
} else {
if (substr($line, $i, 1) == '(') {
$paren_level++;
} else {
if (substr($line, $i, 1) == ')' && $paren_level > 0) {
$paren_level--;
} else {
if (substr($line, $i, 1) == ';' && !$bslash_count && !$paren_level) {
$subline = substr(substr($line, 0, $i), $query_start);
/* is there anything else on the line? */
if (strspn($subline, " \t\n\r") != strlen($subline)) {
/*
* insert a cosmetic newline, if this is not the first
* line in the buffer
*/
if (strlen($query_buf) > 0) {
$query_buf .= "\n";
}
/* append the line to the query buffer */
$query_buf .= $subline;
$query_buf .= ';';
// Execute the query. PHP cannot execute
// empty queries, unlike libpq
$res = @pg_query($conn, $query_buf);
// Call the callback function for display
if ($callback !== null) {
$callback($query_buf, $res, $lineno);
}
// Check for COPY request
if (pg_result_status($res) == 4) {
// 4 == PGSQL_COPY_FROM
while (!feof($fd)) {
$copy = fgets($fd, 32768);
$lineno++;
pg_put_line($conn, $copy);
if ($copy == "\\.\n" || $copy == "\\.\r\n") {
pg_end_copy($conn);
break;
}
}
}
}
$query_buf = null;
$query_start = $i + $thislen;
} else {
if (preg_match('/^[_[:alpha:]]$/', substr($line, $i, 1))) {
$sub = substr($line, $i, $thislen);
while (preg_match('/^[\\$_A-Za-z0-9]$/', $sub)) {
/* keep going while we still have identifier chars */
$this->advance_1($i, $prevlen, $thislen);
$sub = substr($line, $i, $thislen);
}
// Since we're now over the next character to be examined, it is necessary
// to move back one space.
$i -= $prevlen;
}
}
}
}
}
}
}
}
}
}
}
}
// end for
/* Put the rest of the line in the query buffer. */
$subline = substr($line, $query_start);
if ($in_quote || $dol_quote || strspn($subline, " \t\n\r") != strlen($subline)) {
if (strlen($query_buf) > 0) {
$query_buf .= "\n";
}
$query_buf .= $subline;
}
$line = null;
}
// end while
/*
* Process query at the end of file without a semicolon, so long as
* it's non-empty.
*/
if (strlen($query_buf) > 0 && strspn($query_buf, " \t\n\r") != strlen($query_buf)) {
// Execute the query
$res = @pg_query($conn, $query_buf);
// Call the callback function for display
if ($callback !== null) {
$callback($query_buf, $res, $lineno);
}
// Check for COPY request
if (pg_result_status($res) == 4) {
// 4 == PGSQL_COPY_FROM
while (!feof($fd)) {
$copy = fgets($fd, 32768);
$lineno++;
pg_put_line($conn, $copy);
if ($copy == "\\.\n" || $copy == "\\.\r\n") {
pg_end_copy($conn);
break;
}
}
}
}
fclose($fd);
return true;
}