0

I have recently bought a new MacBook Pro. Before I had my MacBook Pro I was working on a website on my desktop computer. And now I want to transfer this code to my new MacBook Pro.

The problem is that when I transfered the code (I put it on Dropbox and simply downloaded it on my MacBook Pro) I started to see lots of error messages in my PHP code.

The error message I”m receiving is:

Warning: Cannot modify header information - headers already sent by (output started at /some/file.php:1) in /some/file.php on line 23

I have done some research on this and it seems that this error is most frequently caused by a new line, simple whitespace or any output before the <?php sign. I have looked through all the places where I have cookies that are being sent in the HTTP request and also where I'm using the header() function. I haven’t detected any output or whitespace that possibly could interfere and cause this problem.

Noteworthy is that the error always says that the output is started at line 1. Which got me thinking if there is some kind of coding differences in the way that the Mac OS X and Windows operating systems handle new lines or white spaces? Or could the Dropbox transfer messed something up?

The code on one of the sites(login.php) which produces the error:

 <?php
    include "mysql_database.php";

    login();

    $id = $_SESSION['Loggedin'];
    setcookie("login", $id, (time()+60*60*24*30));
    header('Location: ' . $_SERVER['HTTP_REFERER']);
?>

login function:

function login() {

    $connection = connecttodatabase();
    $pass = "";
    $user = "";
    $query = "";

    if (isset($_POST['user']) && $_POST['user'] != null) {

        $user = $_POST['user'];

        if (isset($_POST['pass']) && $_POST['pass'] != null) {
            $pass = md5($_POST['pass']);

            $query = "SELECT ID FROM Anvandare WHERE Nickname='$user' AND Password ='$pass'";
        }

    }

    if ($query != "") {
        $id = $connection->query($query);
        $id = mysqli_fetch_assoc($id);
        $id = $id['ID'];

        $_SESSION['Loggedin'] = $id;

    }


    closeconnection($connection);

}

Complete error:

Warning: Cannot modify header information - headers already sent by (output started at /Users/name/GitHub/website/login.php:1) in /Users/namn/GitHub/website/login.php on line 9
  • It's a good idea to post at least the first 23 lines of /some/file.php as it will help reduce the time to diagnose your issue. There are multiple reasons you may be getting these warnings including: the use of short_tags without the proper php.ini setting. Having insufficient error_reporting / logging on Windows where the problem may also have happened. Having automatic output buffering enabled on Windows. You may consider using `ob_start` in your application entry point if you don't mind waiting until the entire response is formed before sending data to the client. – Andrew Mackrodt Jun 11 '14 at 16:16
  • I have extracted the necessary code now. Line 23 corresponds to the line in login.php file where I'm setting up the cookie. I have enabled the full error reporting on windows and yet i still don't have this problem there. I would like to avoid the ob_start and output buffering option found in the php.ini file. This is because in the php.ini file on the server that im going to upload my webpage to later don't have this option turned on and i cant access the php.ini file. Therefor i would rather get these error messages now instead of when the webpage is live. – Marcus Hanikat Jun 11 '14 at 23:11
  • `ob_start` can be controlled by your application code safely irrespective of the php.ini setting. However, your issue may be related to having display_errors = 1 and not calling `session_start` in mysql_database.php. – Andrew Mackrodt Jun 12 '14 at 13:23

3 Answers3

0

Check if there are spaces in front of your php opening tag. Also try resaving the file from notepad++ using the windows (crlr) line endings. (Edit > EOL Conversion > Windows format)

marabunta2048
  • 1,071
  • 1
  • 8
  • 9
  • Checked the code several times for whitespaces without finding any:/ The only way i managed to get the code to work was to resave the code in textwrangler to Mac(CR) linebreaks. The resaved files now works fine. – Marcus Hanikat Jun 11 '14 at 23:16
0

Noteworthy is that the error always says that the output is started at line 1. Which got me thinking if there is some kind of coding differences in the way that the Mac OS X and Windows operating systems handle new lines or white spaces? Or could the Dropbox transfer messed something up?

Don’t redo your code or worry about the header() calls or even the cookie stuff. That is not the issue.

The issue is that Windows line endings are different from Mac line endings. More details here.

Different operating systems use different characters to mark the end of line:

  • Unix / Linux / OS X uses LF (line feed, '\n', 0x0A)
  • Macs prior to OS X use CR (carriage return, '\r', 0x0D)
  • Windows / DOS uses CR+LF (carriage return followed by line feed, '\r\n', 0x0D0A)

And what happens in cases like this is the formatting of the page causes the PHP parser in Apache to choke on the files. Possibly sending content to the browser before you intend to when making header() calls or setting cookies. Meaning technically the screwed up line endings force a “header” to be sent because the file itself is outputting data to the browser inadvertently.

The solution might be to avoid using Dropbox & just copy the files onto a flash drive & transfer it that way. That’s an idea but I am not convinced that Dropbox was the culprit in this. Meaning the issue might still exist even if you copy the files to a flash drive.

Or if that does not work, do as the linked to article suggests & download a good text editing tool like TextWrangler. Just load the files into TextWrangler & then manually change the line endings so they are Mac (CR) and resave the files.

Another long-term solution to this issue might be to use a version control system like git coupled with an account on GitHub to manage your code. The benefit is by pushing code to GitHub & pulling code from GitHub, the process itself will deal with cross-platform line ending headaches. And you don’t need to worry about inadvertent oddities caused by a straight copy of files to a service like DropBox.

But again, pretty convinced this has nothing to do with Dropbox. It’s all about Windows line endings being different from Mac OS X line endings.

EDIT: There are some interesting ideas on how to handle the bulk conversion of Windows line endings to Mac OS X line endings on Mac OS X Hints. The most intrguing one is the use of zip and unzip to facilitate the process. I have not tried this, so caveat emptor! But it does sound like something worth testing since the last line states, BTW, it's the "-a" flag to unzip, that is causing the ascii files to have their lines endings converted.:

I've always used the following (in a file named fixascii):

#!/bin/sh 
zip -qr foo.zip "$@" && unzip -aqo foo.zip && rm foo.zip

And then execute it as:

fixascii [files or directories to convert]

Which has the benefit over most of these other commands in that you can point it with impunity at an entire directory tree and it will process all the files in it and not corrupt any binaries that may happen to have a string of bits in them that look like a line-ending.

I've seen too many times where someone corrupted a ton of images and other binaries, when trying to fix line-endings on text files using dos2unix or tr in combination with find but failed to ensure that only text files were processed. Unzip figure out which files are ascii, converts them, and leaves the binaries alone.

BTW, it's the "-a" flag to unzip, that is causing the ascii files to have their lines endings converted.

And then looking in the official man page for unzip under the -a (convert text files) option; emphasis is mine:

Ordinarily all files are extracted exactly as they are stored (as ''binary'' files). The -a option causes files identified by zip as text files (those with the 't' label in zipinfo listings, rather than 'b') to be automatically extracted as such, converting line endings, end-of-file characters and the character set itself as necessary. (For example, Unix files use line feeds (LFs) for end-of-line (EOL) and have no end-of-file (EOF) marker; Macintoshes use carriage returns (CRs) for EOLs; and most PC operating systems use CR+LF for EOLs and control-Z for EOF. In addition, IBM mainframes and the Michigan Terminal System use EBCDIC rather than the more common ASCII character set, and NT supports Unicode.) Note that zip's identification of text files is by no means perfect; some ''text'' files may actually be binary and vice versa. unzip therefore prints ''[text]'' or ''[binary]'' as a visual check for each file it extracts when using the -a option. The -aa option forces all files to be extracted as text, regardless of the supposed file type.

EDIT: Also, if you have access to a Linux machine, you might want to checkout dos2unix. More details here as well. And found another Stack Overflow question here.

Community
  • 1
  • 1
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
  • 1
    I transfered my project to github from my windows computer, but it did not fix the errors. I found a workaround in the way of creating a new file with CR lining and naming it the same as the previous file(in this case the login.php file) and then copying the code from the file version on windows. Although it works, its quite time consuming... Is there an easier way of doing this? Can i change the line ending for all my files at once? I would like to find a solution where i can transfer my files between my computers seamless – Marcus Hanikat Jun 11 '14 at 20:15
  • @Makka95 Sorry, not off the top of my head. That is the issue thought; Windows line endings versus Mac OS X line endings. I would suggest looking at some of the ideas presented here. Especially the use of `zip` and `unzip` which according to one poster, **BTW, it's the "-a" flag to unzip, that is causing the ascii files to have their lines endings converted.** Sounds cool! Check my edited answer. http://hints.macworld.com/article.php?story=20031018164326986 – Giacomo1968 Jun 11 '14 at 20:29
  • Tested the unzip command, "unzip -a myzipedfiles.zip", in the terminal without success :/ still the same problem. Does it work on .php files or is it just .txt? I also tried the "flip" program without success :( But i did find out that there is an easier way to convert linebreaks in textwrangler. In the small information panel on the bottom there is a option to choose which line breaks to use. I simply changed the linebreaks there and saved the document and it seems to work. Although i still have to do it file by file :/ – Marcus Hanikat Jun 11 '14 at 22:36
  • Makka95 The binary headers in the file on a file system would ensure that PHP files were properly handled as text files. Happy there is some hope in TextWrangler! – Giacomo1968 Jun 11 '14 at 22:39
  • 1
    I'll give it another try tomorrow with the zip solution. Otherwise i think i will turn on the output buffering in my php.ini file and just correct the possible errors on my windows computer later. – Marcus Hanikat Jun 11 '14 at 22:47
  • @Makka95 If you have access to a Linux machine, you might want to checkout [`dos2unix`](http://linuxcommand.org/man_pages/dos2unix1.html). More [details here](http://www.liquidweb.com/kb/dos2unix-removing-hidden-windows-characters-from-files/) as well. And found another Stack Overflow question [here](http://stackoverflow.com/questions/6373888/converting-newline-formatting-from-mac-to-windows). – Giacomo1968 Jun 12 '14 at 02:50
0

Finally found an easy way to fix this! I was looking through the php.ini file when i came across an option which is named: auto_detect_line_endings, and has its default value set to: Off.

The description to this option is:

; If your scripts have to deal with files from Macintosh systems,
; or you are running on a Mac and need to deal with files from
; unix or win32 systems, setting this flag will cause PHP to
; automatically detect the EOL character in those files so that
; fgets() and file() will work regardless of the source of the file.
; http://php.net/auto-detect-line-endings

Which is exactly what i was looking for!

I simply used the ini_set() function at the beginning of my database file(which i load on every php page) and it seems to have solved the problem for me! The ini_set() function also returns the option changed in the php.ini file to normal when script is completed.

Full line of the ini_set() function that i used:

ini_set("auto_detect_line_endings", true);

Thanks for all your help guys!

More info on ini_set() function here: ini_set() function

More info on the auto_detect_line_endings option here: Auto detect line endings option