View Full Version : Custom page throwing: Unable to add cookies, header already sent
fviper
01-28-2011, 05:31 PM
Hey All,
I am trying to write a custom PHP / MySQL-driven page that will live underneath the /forums path, but should (would like it to...) be able to access the VBulletin group membership info ($vbulletin->userinfo[usergroupid]).
I have made several previous pages from templating found at : https://vborg.vbsupport.ru/showthread.php?t=62164 - thank you, btw Gary! However, using templates with what I am trying to make just won't do what I want it to do, so I have reverted to making my own custom pages and creating a separate folder underneath the /forums path.
When I call global.php from a :
require_once("../global.php")
since it's up one directory, it initially looks to be ok. Give it a few minutes (not normal session timeout - 3-4 minutes, tops), and I get the "Unable to add cookies, header already sent" if I refresh, or try to update info on the page. If I navigate back to the main forums page, and refresh, then navigate back to the custom page and refresh - it's fine for a few more minutes - until it once again decides to try to resend cookies (apparently). That line of code is the very first line after the <?PHP tag - so nothing comes before it - no sessions, no variable declarations, nothing.
After deeper research, I saw someone mention that I might have a space somewhere in the code after <?PHP or before ?> I picked through my code, and even put it through validator.w3.org until I had absolutely nothing it could complain about. I even removed all comments I had in the code (not that that should have had any bearing, but hey).
All I need is something along the lines of :
if (($vbulletin->userinfo[usergroupid] == 6) || ($vbulletin->userinfo[usergroupid] == 10))
{
echo '<p><center><a href="cataloot.php">Update Loot</a></center><br />';
}
on the main, public page, and another similar group check on the backend, admin piece. What I have actually works, and works well for my needs - save the oddball "Unable to add cookies" error. Can anyone offer some friendly advice on how best to approach this without using the templates - I have a number of MySQL / Ajax-driven tables that just don't seem to work with Gary's original template suggestions. As a side note, I am using a separate database outside of the vBulletin db to drive these pages. I granted the vb account full privs to my external database - just as a test with no joy.
BTW, I am running VB 3.6.8, PHP 5.2.4, MySQL 5.1.52 - if that helps you look in a particular direction.
Absolutely any constructive comments / suggestions are very much welcome. Security through obscurity just isn't my thing lol. If anyone has any suggestions for mods to that template that would enable to be able to do sql queries as well as PHP code (from what I have read, it's not designed to do this anyways - one reason I abandoned it for this purpose) - I would definitely love to hear your thoughts.
Thanks, in advance!
You may know this already, but "Unable to add cookies, header already sent" I think means that something was written out before the vB code tried to set the headers, and if you don't have any code before the global.php include, then it's probably a warning or error message.
I know you said your problem is happening at a shorter interval than the session timeout, but just FYI, I believe the session "last activity" time is set on most vb pages by the call to "print_output" at the end, which I guess you're not calling in your custom page.
fviper
01-29-2011, 03:09 AM
Here's the top portion of the page that would benefit the most by being able to determine group membership.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" />
<link rel="stylesheet" href="loot.css" type="text/css" />
<link rel="stylesheet" href="themes/default/nlscalendar.css" type="text/css" />
<script src="http://www.wowhead.com/widgets/power.js"></script>
<script src="lib/lang/nlscalendar_i18n_en.js"></script>
<script src="lib/nlscalendar.js"></script>
<script src="lib/nlscalendar_picker.js"></script>
<script type="text/javascript" src="functions.js"></script>
<script type="text/javascript">
var cal=new AOCalendar("cal1");
cal.opt.dtFormat = "$YY-$dm-$dd";
cal.opt.themeDir="themes/default/";
cal.render();
</script>
<title>Loot and Attendance History</title>
</head>
<body onLoad="MM_preloadImages('../images/styles/darkreign/misc/home_on.gif','../images/styles/darkreign/misc/usercp_on.gif','../images/styles/darkreign/misc/members_on.gif','../images/styles/darkreign/misc/register_on.gif','../images/styles/darkreign/misc/calendar_on.gif','../images/styles/darkreign/misc/faq_on.gif')"><table style="background: url(../images/styles/darkreign/misc/header_level1_bg.gif);" border="0" width="90%" align="center" cellpadding="0" cellspacing="0">
<tr>
<td width="103"><a href="../index.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Home','','../images/styles/darkreign/misc/home_on.gif',1)"><img src="../images/styles/darkreign/misc/home_off.gif" alt="Home" name="Home" border="0"/></a></td>
<td width="103"><a href="../usercp.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('UserCP','','../images/styles/darkreign/misc/usercp_on.gif',1)"><img src="../images/styles/darkreign/misc/usercp__off.gif" alt="UserCP" name="UserCP" border="0"/></a></td>
<td width="101"><a href="../memberlist.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Members','','../images/styles/darkreign/misc/members_on.gif',1)"><img src="../images/styles/darkreign/misc/members__off.gif" alt="Memberlist" name="Members" border="0"/></a></td>
<td width="103"><a href="../register.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Register','','../images/styles/darkreign/misc/register_on.gif',1)"><img src="../images/styles/darkreign/misc/register__off.gif" alt="Register" name="Register" border="0"/></a></td>
<td width="102"><a href="../calendar.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Calendar','','../images/styles/darkreign/misc/calendar_on.gif',1)"><img src="../images/styles/darkreign/misc/calendar__off.gif" alt="Calendar" name="Calendar" border="0"/></a></td>
<td><a href="faq.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('FAQ','','../images/styles/darkreign/misc/faq_on.gif',1)"><img name="FAQ" border="0" src="../images/styles/darkreign/misc/faq__off.gif" alt="FAQ"/></a></td>
</tr>
</table>
<table style="background: url(../images/styles/darkreign/misc/header_level2_bg.gif);" height="80" border="0" width="90%" align="center" cellpadding="0" cellspacing="0">
<tr><td align="left" valign="middle">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="750" height="100" id="driven_header" >
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="../images/styles/darkreign/misc/driven_header.swf" />
<param name="loop" value="false" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<embed src="../images/styles/darkreign/misc/driven_header.swf" loop="false" quality="high" bgcolor="#ffffff" width="750" height="100" name="driven_header" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" />
</object>
</td></tr>
</table>
<?php
require_once("../global.php");
include('auth.php');
@$user = $_GET['userid'];
@$instance = $_GET['instanceid'];
@$encounter = $_GET['encountername'];
@$lootname = $_GET['lootname'];
I've tried using the $_COOKIE["bbuserid"] to determine username - which I can from that cookie. After digging through that cookie, there's nothing in it that would aid in group discovery. If you don't mind, can you explain the "print_output" in more detail?
Thanks!
If you don't mind, can you explain the "print_output" in more detail?
This is admittedly based on my memory of something I worked on over a year ago, but - the session timeout is done by comparing the last activity time (saved in the session table) with the current time, and the current time is then saved as the "last activity". The actual update of the session table is done in exec_shut_down() which is called from print_output() (both of those are in includes/functions.php). So if you're not calling one of those then your script probably isn't updating the lastactivity. But I don't know if that has anything to do with the problem you're having - probably it doesn't. (I also could be remembering wrong).
I'm kind of surprised your code works because global.php includes init.php, and it looks like that exits if THIS_SCRIPT isn't defined.
I don't know how important having the actual group is to you, but of course if you read cookies or some other info coming from the user then it could be hacked. If that's not an issue then one thing you might be able to do is set your own cookie somewhere in the vb code (via a plugin), but I don't know where you'd do that offhand, and you might have to deal with making sure it gets reset if the group should change, and what to if it's not sent, etc.
I know other people have had issues with trying to include global.php from another directory, so maybe that has something to do with the problems in your current code. I seem to remember someone recently was doing a chdir to the forum directory bbefore including global.php, then doing a chdir back to their custom directory.
ETA: ...one other thought - you mentioned before that your global.php was the first thing after "<?php", but it didn't occur to me that you might have something before that in the file. The HTML you have at the top might be the cause of the "can't set cookie" message you get sometimes. You might try including global.php at the top even if you don't need it until later.
Anyway, sorry I'm not more help - I'm sure if anyone else has ideas they will chime in.
fviper
01-31-2011, 01:41 PM
Good thinking there - I appreciate the input. I did have 'THIS_SCRIPT' defined in there at one point, but I thought that the primary purpose of that was for VB to be able to see which template you were calling? Here's one of my other templates that I used to track donations on the site:
<?php
// ####################### SET PHP ENVIRONMENT ###########################
error_reporting(E_ALL & ~E_NOTICE);
// #################### DEFINE IMPORTANT CONSTANTS #######################
define('NO_REGISTER_GLOBALS', 1);
define('THIS_SCRIPT', 'donations'); // change this depending on your filename
// ################### PRE-CACHE TEMPLATES AND DATA ######################
// get special phrase groups
$phrasegroups = array(
);
// get special data templates from the datastore
$specialtemplates = array(
);
// pre-cache templates used by all actions
$globaltemplates = array(
'DONATIONS',
);
// pre-cache templates used by specific actions
$actiontemplates = array(
);
// ######################### REQUIRE BACK-END ############################
require_once('./global.php');
// ################################################## #####################
// ######################## START MAIN SCRIPT ############################
// ################################################## #####################
$navbits = array();
$navbits[$parent] = 'Driven Guild Donations';
$navbits = construct_navbits($navbits);
eval('$navbar = "' . fetch_template('navbar') . '";');
eval('print_output("' . fetch_template('donate') . '");');
?>
This code does fine (Gary's template guide) - as it's a VB-only driven page. If I could get the MySQL / PHP / Ajax to play nicely with VB templates, I would most certainly go that route as it would be better integrated with VB. Without calling a template, the code seemed useless to me - but hey... I admit VB's templating methods make my eyes glaze over at times lol. I'll try defining that again in my code. Keep your fingers crossed ;) It would be cool if it was something that simple!
--------------- Added 1296502750 at 1296502750 ---------------
Hey kh99,
I combined a few of your suggestions, and it looks like that has done the trick. It didn't dawn on me either that some of the javascript calls or header info could be skewed by a basic table at the top of a page, but hey... I rearranged the head and meta declarations to being after <?php, and everything appears to be fat, dumb and happy lol.
<?php
define('NO_REGISTER_GLOBALS', 1);
define('THIS_SCRIPT', 'cataloot');
require_once("../global.php");
include('auth.php');
@$user = $_GET['userid'];
@$instance = $_GET['instanceid'];
@$encounter = $_GET['encountername'];
@$lootname = $_GET['lootname'];
$showlistbits = '';
$altclass = 'alt1';
$link = mysql_connect("localhost",$username,$pass);
$result = mysql_select_db("adamsre_lootad");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" />
<link rel="stylesheet" href="loot.css" type="text/css" />
<link rel="stylesheet" href="themes/default/nlscalendar.css" type="text/css" />
<script src="http://www.wowhead.com/widgets/power.js"></script>
<script src="lib/lang/nlscalendar_i18n_en.js"></script>
<script src="lib/nlscalendar.js"></script>
<script src="lib/nlscalendar_picker.js"></script>
<script type="text/javascript" src="functions.js"></script>
<script type="text/javascript">
var cal=new AOCalendar("cal1");
cal.opt.dtFormat = "$YY-$dm-$dd";
cal.opt.themeDir="themes/default/";
cal.render();
</script>
<title>Loot and Attendance History</title>
</head>
<body onLoad="MM_preloadImages('../images/styles/darkreign/misc/home_on.gif','../images/styles/darkreign/misc/usercp_on.gif','../images/styles/darkreign/misc/members_on.gif','../images/styles/darkreign/misc/register_on.gif','../images/styles/darkreign/misc/calendar_on.gif','../images/styles/darkreign/misc/faq_on.gif')"><table style="background: url(../images/styles/darkreign/misc/header_level1_bg.gif);" border="0" width="90%" align="center" cellpadding="0" cellspacing="0">
<tr>
<td width="103"><a href="../index.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Home','','../images/styles/darkreign/misc/home_on.gif',1)"><img src="../images/styles/darkreign/misc/home_off.gif" alt="Home" name="Home" border="0"/></a></td>
<td width="103"><a href="../usercp.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('UserCP','','../images/styles/darkreign/misc/usercp_on.gif',1)"><img src="../images/styles/darkreign/misc/usercp__off.gif" alt="UserCP" name="UserCP" border="0"/></a></td>
<td width="101"><a href="../memberlist.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Members','','../images/styles/darkreign/misc/members_on.gif',1)"><img src="../images/styles/darkreign/misc/members__off.gif" alt="Memberlist" name="Members" border="0"/></a></td>
<td width="103"><a href="../register.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Register','','../images/styles/darkreign/misc/register_on.gif',1)"><img src="../images/styles/darkreign/misc/register__off.gif" alt="Register" name="Register" border="0"/></a></td>
<td width="102"><a href="../calendar.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('Calendar','','../images/styles/darkreign/misc/calendar_on.gif',1)"><img src="../images/styles/darkreign/misc/calendar__off.gif" alt="Calendar" name="Calendar" border="0"/></a></td>
<td><a href="faq.php" onmouseOut="MM_swapImgRestore()" onmouseOver="MM_swapImage('FAQ','','../images/styles/darkreign/misc/faq_on.gif',1)"><img name="FAQ" border="0" src="../images/styles/darkreign/misc/faq__off.gif" alt="FAQ"/></a></td>
</tr>
</table>
<table style="background: url(../images/styles/darkreign/misc/header_level2_bg.gif);" height="80" border="0" width="90%" align="center" cellpadding="0" cellspacing="0">
<tr><td align="left" valign="middle">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="750" height="100" id="driven_header" >
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="../images/styles/darkreign/misc/driven_header.swf" />
<param name="loop" value="false" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<embed src="../images/styles/darkreign/misc/driven_header.swf" loop="false" quality="high" bgcolor="#ffffff" width="750" height="100" name="driven_header" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" />
</object>
</td></tr>
</table>
<?php
is what I have now - I did define 'THIS_SCRIPT', though, in all honesty, I think was simply rearranging things that ultimately did the trick. Thanks a TON for all of your help!
vBulletin® v3.8.12 by vBS, Copyright ©2000-2025, vBulletin Solutions Inc.