Jump to content

header trouble

- - - - -

  • Please log in to reply
3 replies to this topic

#1
logicPwn

logicPwn

    Learning Programmer

  • Members
  • PipPipPip
  • 91 posts
Says headers are already sent out but can't find where. Heres output http://tlokzz.info/u...ad.php?app_id=1

This is the script
<?php

require("database.class.php");


// db init

$db = new Database("localhost", "", "", "");

$db->connect();


// parse get vars

if (!isset($_GET['app_id'])) {

    die("error: no app_id");

}

$id = $db->escape($_GET['app_id']);


// get app data

$app = array();

$app = $db->query_first("SELECT * FROM apps WHERE id='" . $id . "'");


// add one to download count

$data = array();

$data['downloads'] = $app['downloads']++;

$db->query_update("apps", $data, "id='" . $id . "'");


header('Content-Description: File Transfer');

header('Content-Type: application/octet-stream');

header('Content-Disposition: attachment; filename=' . basename($app['download_link']));

header('Content-Transfer-Encoding: binary');

header('Expires: 0');

header('Cache-Control: must-revalidate');

header('Pragma: public');

header('Content-Length: ' . filesize($app['download_link']));

ob_clean();

flush();

readfile($app['download_link']);

exit;

?>

This is database.class.php
<?php

# Name: Database.class.php

# File Description: MySQL Class to allow easy and clean access to common mysql commands

# Author: ricocheting

# Web: http://www.ricocheting.com/

# Update: 2010-05-08

# Version: 2.2.5

# Copyright 2003 ricocheting.com



/*

    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 3 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, see <http://www.gnu.org/licenses/>.

*/




//require("config.inc.php");

//$db = new Database(DB_SERVER, DB_USER, DB_PASS, DB_DATABASE);



###################################################################################################

###################################################################################################

###################################################################################################

class Database {



var $server   = ""; //database server

var $user     = ""; //database login name

var $pass     = ""; //database login password

var $database = ""; //database name

var $pre      = ""; //table prefix



#######################

//internal info

var $error = "";

var $errno = 0;


//number of rows affected by SQL query

var $affected_rows = 0;


var $link_id = 0;

var $query_id = 0;



#-#############################################

# desc: constructor

function Database($server, $user, $pass, $database, $pre=''){

    $this->server=$server;

    $this->user=$user;

    $this->pass=$pass;

    $this->database=$database;

    $this->pre=$pre;

}#-#constructor()



#-#############################################

# desc: connect and select database using vars above

# Param: $new_link can force connect() to open a new link, even if mysql_connect() was called before with the same parameters

function connect($new_link=false) {

    $this->link_id=@mysql_connect($this->server,$this->user,$this->pass,$new_link);


    if (!$this->link_id) {//open failed

        $this->oops("Could not connect to server: <b>$this->server</b>.");

        }


    if(!@mysql_select_db($this->database, $this->link_id)) {//no database

        $this->oops("Could not open database: <b>$this->database</b>.");

        }


    // unset the data so it can't be dumped

    $this->server='';

    $this->user='';

    $this->pass='';

    $this->database='';

}#-#connect()



#-#############################################

# desc: close the connection

function close() {

    if(!@mysql_close($this->link_id)){

        $this->oops("Connection close failed.");

    }

}#-#close()



#-#############################################

# Desc: escapes characters to be mysql ready

# Param: string

# returns: string

function escape($string) {

    if(get_magic_quotes_runtime()) $string = stripslashes($string);

    return @mysql_real_escape_string($string,$this->link_id);

}#-#escape()



#-#############################################

# Desc: executes SQL query to an open connection

# Param: (MySQL query) to execute

# returns: (query_id) for fetching results etc

function query($sql) {

    // do query

    $this->query_id = @mysql_query($sql, $this->link_id);


    if (!$this->query_id) {

        $this->oops("<b>MySQL Query fail:</b> $sql");

        return 0;

    }

    

    $this->affected_rows = @mysql_affected_rows($this->link_id);


    return $this->query_id;

}#-#query()



#-#############################################

# desc: fetches and returns results one line at a time

# param: query_id for mysql run. if none specified, last used

# return: (array) fetched record(s)

function fetch_array($query_id=-1) {

    // retrieve row

    if ($query_id!=-1) {

        $this->query_id=$query_id;

    }


    if (isset($this->query_id)) {

        $record = @mysql_fetch_assoc($this->query_id);

    }else{

        $this->oops("Invalid query_id: <b>$this->query_id</b>. Records could not be fetched.");

    }


    return $record;

}#-#fetch_array()



#-#############################################

# desc: returns all the results (not one row)

# param: (MySQL query) the query to run on server

# returns: assoc array of ALL fetched results

function fetch_all_array($sql) {

    $query_id = $this->query($sql);

    $out = array();


    while ($row = $this->fetch_array($query_id)){

        $out[] = $row;

    }


    $this->free_result($query_id);

    return $out;

}#-#fetch_all_array()



#-#############################################

# desc: frees the resultset

# param: query_id for mysql run. if none specified, last used

function free_result($query_id=-1) {

    if ($query_id!=-1) {

        $this->query_id=$query_id;

    }

    if($this->query_id!=0 && !@mysql_free_result($this->query_id)) {

        $this->oops("Result ID: <b>$this->query_id</b> could not be freed.");

    }

}#-#free_result()



#-#############################################

# desc: does a query, fetches the first row only, frees resultset

# param: (MySQL query) the query to run on server

# returns: array of fetched results

function query_first($query_string) {

    $query_id = $this->query($query_string);

    $out = $this->fetch_array($query_id);

    $this->free_result($query_id);

    return $out;

}#-#query_first()



#-#############################################

# desc: does an update query with an array

# param: table (no prefix), assoc array with data (doesn't need escaped), where condition

# returns: (query_id) for fetching results etc

function query_update($table, $data, $where='1') {

    $q="UPDATE `".$this->pre.$table."` SET ";


    foreach($data as $key=>$val) {

        if(strtolower($val)=='null') $q.= "`$key` = NULL, ";

        elseif(strtolower($val)=='now()') $q.= "`$key` = NOW(), ";

        elseif(preg_match("/^increment\((\-?\d+)\)$/i",$val,$m)) $q.= "`$key` = `$key` + $m[1], "; 

        else $q.= "`$key`='".$this->escape($val)."', ";

    }


    $q = rtrim($q, ', ') . ' WHERE '.$where.';';


    return $this->query($q);

}#-#query_update()



#-#############################################

# desc: does an insert query with an array

# param: table (no prefix), assoc array with data

# returns: id of inserted record, false if error

function query_insert($table, $data) {

    $q="INSERT INTO `".$this->pre.$table."` ";

    $v=''; $n='';


    foreach($data as $key=>$val) {

        $n.="`$key`, ";

        if(strtolower($val)=='null') $v.="NULL, ";

        elseif(strtolower($val)=='now()') $v.="NOW(), ";

        else $v.= "'".$this->escape($val)."', ";

    }


    $q .= "(". rtrim($n, ', ') .") VALUES (". rtrim($v, ', ') .");";


    if($this->query($q)){

        //$this->free_result();

        return mysql_insert_id($this->link_id);

    }

    else return false;


}#-#query_insert()



#-#############################################

# desc: throw an error message

# param: [optional] any custom error to display

function oops($msg='') {

    if($this->link_id>0){

        $this->error=mysql_error($this->link_id);

        $this->errno=mysql_errno($this->link_id);

    }

    else{

        $this->error=mysql_error();

        $this->errno=mysql_errno();

    }

    ?>

        <table align="center" border="1" cellspacing="0" style="background:white;color:black;width:80%;">

        <tr><th colspan=2>Database Error</th></tr>

        <tr><td align="right" valign="top">Message:</td><td><?php echo $msg; ?></td></tr>

        <?php if(!empty($this->error)) echo '<tr><td align="right" valign="top" nowrap>MySQL Error:</td><td>'.$this->error.'</td></tr>'; ?>

        <tr><td align="right">Date:</td><td><?php echo date("l, F j, Y \a\\t g:i:s A"); ?></td></tr>

        <?php if(!empty($_SERVER['REQUEST_URI'])) echo '<tr><td align="right">Script:</td><td><a href="'.$_SERVER['REQUEST_URI'].'">'.$_SERVER['REQUEST_URI'].'</a></td></tr>'; ?>

        <?php if(!empty($_SERVER['HTTP_REFERER'])) echo '<tr><td align="right">Referer:</td><td><a href="'.$_SERVER['HTTP_REFERER'].'">'.$_SERVER['HTTP_REFERER'].'</a></td></tr>'; ?>

        </table>

    <?php

}#-#oops()



}//CLASS Database

###################################################################################################


?> 

If it matters, I'm using System.Net.DownloadFileAsync() and using that url that sends out headers and forces a download. Having my doubts that it will happen like that and download the end result not the page source.

#2
grisha

grisha

    Learning Programmer

  • Members
  • PipPipPip
  • 35 posts
Try to remove the PHP end tag from the database.class.php file, and also don't use UTF8 with BOM.

#3
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,124 posts
  • Location:Vancouver, Eh! Cleverness: 200
From visiting the page, there are some errors including
Warning: filesize() [function.filesize]: stat failed for http://tlokzz.info/updater/files/cu_1200.exe in /home/tlokzzi1/public_html/updater/api/download.php on line 30
Warning: readfile(http://tlokzz.info/updater/files/cu_1200.exe) [function.readfile]: failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/tlokzzi1/public_html/updater/api/download.php on line 33

Those push before headers even if the previous problem were fixed.

At here:
output started at /home/tlokzzi1/public_html/updater/api/database.class.php:[B]264[/B]

There may be a line of which fails at 264 in this file (i.e. failed transaction with your database, closing tag ?>) that causes an issue even before the first header call (not limited to the filesystem errors above).

As Grisha has mentioned it may possibly as well be a byte order mark(0xFFEE in UTF-8, an invisible nonbreaking space) set by your text processor. Most have the option to save in ASCII or without this UTF-8 byte order mark.

Some debugging may prove useful.

Side notes: The file name is usually wrapped around double quotes in the header content-disposition. "SHOULD be" is used however in the related RFCs, and is probably not significant. Your die()'s will always cause headers to fail, you may wish to implement something that does not require output (i.e. turning error display off, logging on, sending users to error page instead of abortion)
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.

#4
logicPwn

logicPwn

    Learning Programmer

  • Members
  • PipPipPip
  • 91 posts
Well since you said that I kinda figured that it might be because I haven't uploaded the file it's looking for yet. So I did it and it didn't change.

I commented out the die in my script but no change. Maybe it's all the outputs that DB class does. I think I'm going to rewrite it. Also the UTF-8 part. Where do you change this?

Oh and I lied above. It did change a bit when adding the file to it's spot. It added a bunch of crazy chars I'm assuming it's trying to read it binary and outputting it in the page.

Starting to feel a little over my head. Need to do a lot of research obviously.

Edit: Little research shows that you guys are talking about the format UTF-8 that the file is stored in on the server. PHP doesn't interpret it so APACHE does and any output screws up header work because it sent out data. Checked around in my IDE, NetBeans, for changing it and can't find anything.

2nd Edit: Removed ?> in DB class and it worked. Weird.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users