I need help diagnosing this segfault.  Because I have failed.
It is clockwork reproducible.

Does anyone else (in unix / linux) have the same segfault after
opening the streams tree in the music browser?

I think something is compiling / linking / loading wrong.  I notice
that when I touch Http.cpp, that the Http.o and freeamp executable and
plugins/musicbrowser.ui and plugins/freeamp.ui are re-compiled.

When I add output to this function:

int Http::WriteToBuffer(unsigned char *buffer, unsigned int size)
{
    cerr << "WriteToBuffer " << size << endl << flush;
    if (m_buffer == NULL)
    {
        _you_are_here;
        m_bufferSize = kBufferSize;
        m_buffer = new unsigned char[m_bufferSize];
    }
    _show_args1(m_buffer);
    ...
    ...
    return size;
}

That it does NOT output any message.  This function is called from
this sequence in Download (line numbers for me in left column):

483: _show_args1(wcount);
484: _show_args3(m_bufferSize,m_bytesInBuffer,m_buffer);
485: wcount = this->Http::WriteToBuffer((unsigned char *)cp,
486:                                   total - (cp-buffer));
487: _show_args1(wcount);
488: _show_args3(m_bufferSize,m_bytesInBuffer,m_buffer);

This does produce output:

@ lib/http/src/Http.cpp : 483 : enum Error Http::Download(const class string &, bool)
args: wcount=0
@ lib/http/src/Http.cpp : 484 : enum Error Http::Download(const class string &, bool)
args: m_bufferSize=0, m_bytesInBuffer=0, m_buffer=(null)
@ lib/http/src/Http.cpp : 487 : enum Error Http::Download(const class string &, bool)
args: wcount=1804
@ lib/http/src/Http.cpp : 488 : enum Error Http::Download(const class string &, bool)
args: m_bufferSize=1804, m_bytesInBuffer=0, m_buffer=
[2]+  Segmentation fault      /opt/freeamp-mine/bin/freeamp

So even though the WriteToBuffer does not seems to execute the output
to cerr, it does change m_buffer and return size to wcount.  I cannot
trace this in gdb, I set a breakpoint on Http::Download but it passed
right over it.

I am guessing my dificulty may lie in the way plugins are loaded and
symbols are resolved?  Is gdb setting a breakpoint in freeamp's version
of Http.o and not seeing the one in musicbrowser.ui?

I still do not understand how musicbrowser.ui writes to cerr in
Download but not in WriteToBuffer.

I am out of ideas.
I am attaching the header file that defines the macros I am using,
for completeness, and my copy of Http.cpp.

I am running RH 6.2/HelixGnome with gcc 2.91.66
The make output from touching Http.cpp is 

[1525|ckuklewicz /usr/local/src/freeamp/freeamp-mine]$ make    
for p in base base/beos base/beos/src base/src base/unix base/unix/src  dlm dlm/rmp io 
io/alsa io/alsa/unix io/alsa/unix/linux io/alsa/unix/linux/src io/esound io/esound/src 
io/http io/local io/obs io/src io/soundcard io/soundcard/beos io/soundcard/unix 
io/soundcard/beos io/soundcard/unix/linux  io/soundcard/unix/linux/src 
io/soundcard/beos/src io/soundcard/unix/linux/src  io/wavout io/wavout/src 
io/wavout/include io/signature lib lib/xml lib/xml/src lib/http lib/http/src lib/zlib 
lmc lmc/xingmp3 lmc/xingmp3/src lib/gdbm lib/zlib/src lmc/vorbis  plm plm/metadata 
plm/playlist plm/portable plm/portable/pmp300 lmc/xingmp3/src plm/metadata/id3v1 
plm/metadata/id3v2  plm/metadata/misc plm/playlist/m3u plm/portable/pmp300/sba ui 
ui/download ui/download/unix ui/freeamp ui/freeamp/beos  ui/cmdline 
ui/download/unix/src ui/freeamp/beos/src  ui/freeamp/tools ui/freeamp/unix ui/irman 
ui/lcd ui/musicbrowser ui/freeamp/src ui/freeamp/tools/src ui/freeamp/unix/src 
ui/musicbrowser/src ui/musicbrowser/unix ui/mpg123 plm/playlist/pls ui/irman/src 
ui/lcd/src ui/musicbrowser/unix/src ui/ncurses update update/unix lmc/cd lmc/cd/src 
io/cd io/cd/unix  io/cd/unix/src lib/unzip lib/unzip/src ftc ftc/kjofol ftc/winamp 
plm/metadata/cddb base/aps lmc/vorbis/src io/signature/src lib/musicbrainz 
lib/musicbrainz/expat lib/musicbrainz/expat/xmlparse lib/musicbrainz/expat/xmltok 
lib/musicbrainz/osdep lib/musicbrainz/lib; do \
  test -d $p || mkdir $p; \
        done
c++ -I. -I. -I./config -DUNIX_LIBDIR=\"/opt/freeamp-mine//lib\" -Dlinux -I. 
-I./lib/gdbm -I./base/include -I./config -I./io/include -I./ui/include -I./lmc/include 
-I./base/unix/include -I./base/unix/linux/include -I./io/esound/include 
-I./ui/musicbrowser/unix/include -I./ui/freeamp/include -I./ui/freeamp/unix/include 
-I./ui/download/unix/include -I./ui/musicbrowser/include -I./ftc/kjofol 
-I./io/soundcard/unix/linux/include -I./lmc/xingmp3/include -I./lmc/cd/include 
-I./plm/portable/pmp300/sba -I./lib/xml/include -I./lib/zlib/include 
-I./lib/unzip/include -I./io/cd/unix/include -I./base/aps -I./io/wavout/include 
-I./ui/lcd/include -I./ui/irman/include -I./lib/http/include -I./io/signature/include 
-I./lib/musicbrainz/lib -I./lib/musicbrainz/expat/xmltok 
-I./lib/musicbrainz/expat/xmlparse -I./lmc/vorbis/include -Wall -g -O0 
-I/usr/lib/glib/include -I/usr/X11R6/include -I/usr/lib/glib/include 
-I/usr/X11R6/include -D_REENTRANT    -c lib/http/src/Http.cpp -o lib/http/src/Http.o
test -d lib/http/lib || mkdir lib/http/lib
ar -r lib/http/lib/libfahttp.a lib/http/src/Http.o
c++  -Wl,-export-dynamic  -o freeamp base/src/log.o base/src/player.o 
base/src/musiccatalog.o base/src/playlist.o base/src/propimpl.o base/src/registrar.o 
base/src/registry.o base/src/thread.o io/src/eventbuffer.o base/src/prefixprefs.o 
base/src/preferences.o base/src/debug.o base/src/utility.o base/src/database.o  
base/src/downloadmanager.o base/src/errors.o io/src/pullbuffer.o io/src/tstream.o 
base/src/undomanager.o  base/src/timer.o base/src/missingfile.o io/src/pipeline.o 
base/unix/src/bootstrap.o base/unix/src/unixprefs.o base/unix/src/win32impl.o 
base/unix/src/pthreadthread.o base/unix/src/debug.o base/unix/src/mutex.o  
base/unix/src/semaphore.o base/unix/src/utility.o base/aps/FAMetaUnit.o 
base/aps/apsinterface.o  base/aps/apsplaylist.o base/aps/gencrc.o base/aps/hosttonet.o 
 base/aps/nettohost.o base/aps/comsocket.o base/aps/apsconvert.o base/aps/YPClient.o 
base/aps/uuid.o base/aps/slclient.o lib/gdbm/lib/libfagdbm.a lib/xml/lib/libfaxml.a  
lib/zlib/lib/libzlib.a lib/http/lib/libfahttp.a -Wl,-export-dynamic -ldl -lpthread  
-lmusicbrainz -lnsl 
test -d plugins || mkdir plugins
make -f Makefile-plugins - plugins-cc
make[1]: Entering directory `/usr/local/src/freeamp/freeamp-mine'
test -d lib/http/lib || mkdir lib/http/lib
ar -r lib/http/lib/libfahttp.la lib/http/src/Http.o
c++ -shared -Wl,-export-dynamic -o plugins/musicbrowser.ui 
ui/musicbrowser/unix/src/gtkmusicbrowser.o ui/musicbrowser/unix/src/browsermenu.o 
ui/musicbrowser/unix/src/browsertree.o ui/musicbrowser/unix/src/browserlist.o 
ui/musicbrowser/unix/src/musicbrowser.o  ui/musicbrowser/unix/src/infoeditor.o  
ui/musicbrowser/unix/src/fileselector.o  ui/musicbrowser/unix/src/musicsearch.o  
ui/musicbrowser/unix/src/gtkmessagedialog.o  ui/musicbrowser/unix/src/introwizard.o 
ui/musicbrowser/unix/src/missingfileui.o ui/musicbrowser/src/FreeAmpStreams.o 
lib/xml/src/Parse.lo lib/http/lib/libfahttp.la -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk 
-rdynamic -lgmodule -lgthread -lglib -lpthread -ldl -lXi -lXext -lX11 -lm
c++ -shared -Wl,-export-dynamic -o plugins/freeamp.ui ui/freeamp/src/Theme.doh 
ui/freeamp/src/Bitmap.o  ui/freeamp/src/Canvas.o ui/freeamp/src/SliderControl.o  
ui/freeamp/src/VSliderControl.o ui/freeamp/src/Panel.o ui/freeamp/src/Window.o 
ui/freeamp/src/ButtonControl.o  ui/freeamp/src/Control.o ui/freeamp/src/TextControl.o  
ui/freeamp/src/DialControl.o ui/freeamp/src/Font.o  ui/freeamp/src/FreeAmpTheme.o 
ui/freeamp/src/ThemeZip.o  ui/freeamp/src/MultiStateControl.o 
ui/freeamp/src/Headlines.o ui/freeamp/src/ForeignTheme.o base/src/utility.lo 
ui/freeamp/src/PixFontControl.o ui/freeamp/src/PixTimeControl.o 
ui/freeamp/src/Equalizer.o ui/freeamp/src/PixSliderControl.o lib/zlib/lib/libzlib.la 
lib/xml/src/Parse.lo lib/unzip/lib/libunzip.la lib/http/lib/libfahttp.la 
ui/freeamp/unix/src/GTKFont.o ui/freeamp/unix/src/GTKUtility.o  
ui/freeamp/unix/src/GTKMessageDialog.o  ui/freeamp/unix/src/GTKWindow.o 
ui/freeamp/unix/src/GTKBitmap.o  ui/freeamp/unix/src/GTKCanvas.o 
ui/freeamp/unix/src/ttfont.o  ui/freeamp/unix/src/ThemeManager.o  
ui/freeamp/unix/src/GTKPreferenceWindow.o  ui/freeamp/unix/src/GTKFileSelector.o   
-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lgthread -lglib -lpthread 
-ldl -lXi -lXext -lX11 -lm -lttf -L/usr/lib -lgdk_pixbuf -L/usr/lib -L/usr/X11R6/lib 
-lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm
make[1]: Leaving directory `/usr/local/src/freeamp/freeamp-mine'
#ifndef __TRACER_H_
#define __TRACER_H_

#include <iostream>
#include <glib.h>

inline void _real_assert(bool b,const char *file,int line,
                         const char *func, const char *msg) 
{
    if (!b) {
        cerr << endl << "! " << msg << " failed : " << file 
             << " : " << line << " : " << func << endl << flush;
        exit(1);
    }
}

inline void _real_message(const char *file,int line,
                          const char *func, const char *msg) 
{
    cerr << "$ Message : " << file << " : "
         << line << " : " << func << " : " << msg << endl << flush;
}

// Macros to help debug that call the above functions

#define _assert(__f__) _real_assert((__f__),__FILE__,__LINE__, \
 G_GNUC_PRETTY_FUNCTION,"_assert " #__f__)

#define _nullChk(__p__) _real_assert(NULL!=(__p__),__FILE__,__LINE__, \
 G_GNUC_PRETTY_FUNCTION,"_nullChk " #__p__)

#define _message(__m__) _real_message(__FILE__,__LINE__, \
 G_GNUC_PRETTY_FUNCTION,__m__)

#define _never_get_here _real_assert(false,__FILE__,__LINE__, \
 G_GNUC_PRETTY_FUNCTION,"_never_get_here")

// Execution tracing macros for debugging
#define _you_are_here do { cerr << "@ " << __FILE__ << " : " << __LINE__ \
 << " : " << G_GNUC_PRETTY_FUNCTION << endl; } while(0)

#define _show_args0() _you_are_here;

#define _show_args1(Arg1)  do { _you_are_here; cerr << "args: " \
 << #Arg1 << "=" << (Arg1) \
 << endl << flush; } while (0)

#define _show_args2(Arg1,Arg2)  do { _you_are_here; cerr << "args: " \
 << #Arg1 << "=" << (Arg1)  \
 << ", " << #Arg2 << "=" << (Arg2) \
 << endl << flush; } while (0)

#define _show_args3(Arg1,Arg2,Arg3) do { _you_are_here; \
 cerr << "args: " \
 << #Arg1 << "=" << (Arg1)  \
 << ", " << #Arg2 << "=" << (Arg2) \
 << ", " << #Arg3 << "=" << (Arg3) \
 << endl << flush; } while (0)

#define _show_args4(Arg1,Arg2,Arg3,Arg4) do { _you_are_here; \
 cerr << "args: " \
 << #Arg1 << "=" << (Arg1)  \
 << ", " << #Arg2 << "=" << (Arg2) \
 << ", " << #Arg3 << "=" << (Arg3) \
 << ", " << #Arg4 << "=" << (Arg4) \
 << endl << flush; } while (0)

#define _show_args5(Arg1,Arg2,Arg3,Arg4,Arg5) do { _you_are_here; \
 cerr << "args: " \
 << #Arg1 << "=" << (Arg1)  \
 << ", " << #Arg2 << "=" << (Arg2) \
 << ", " << #Arg3 << "=" << (Arg3) \
 << ", " << #Arg4 << "=" << (Arg4) \
 << ", " << #Arg5 << "=" << (Arg5) \
 << endl << flush; } while (0)

#endif
/*____________________________________________________________________________
        
   FreeAmp - The Free MP3 Player

   Copyright (C) 2000 EMusic.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 2 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, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        
   $Id: Http.cpp,v 1.12 2000/09/01 10:57:59 ijr Exp $
____________________________________________________________________________*/

#include "config.h"

#include <stdio.h> 
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include <fcntl.h>    
#include <errno.h>    

#ifdef WIN32
#include <io.h>
#else
#undef socklen_t
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#endif

#if defined(unix) || defined(__BEOS__) || defined(_BSD_SOURCE)
#define SOCKET int
#endif

#if defined(unix) || defined(_BSD_SOURCE)
#include <arpa/inet.h>
#define closesocket(x) close(x)
#define O_BINARY 0
#endif  

#include "Http.h"
#include "tracer.h"
#ifndef min
#define min(a, b)  (((a) < (b)) ? (a) : (b))
#endif

const unsigned short kHttpPort = 80;
const unsigned int kMaxHostNameLen = 64;
const unsigned int kMaxURLLen = 1024;
const unsigned int kBufferSize=8192;

#define DB printf("%s:%d\n", __FILE__, __LINE__);

Http::Http(FAContext *context)
{
    m_exit = false;
    m_context = context;
    m_file = NULL;
    m_buffer = NULL;
    _show_args1(m_buffer);
    m_bytesInBuffer = 0;
    m_bufferSize = 0;
}

Http::~Http(void)
{
    if (m_buffer)
    {
       _show_args1(m_buffer);
       delete m_buffer;
       m_buffer = NULL;
       _show_args1(m_buffer);
    }

    if (m_file)
        fclose(m_file);
}

Error Http::DownloadToString(const string &url, string &page)
{
    _show_args5(url,page,m_bytesInBuffer,m_bufferSize,m_buffer);
    Error eRet;

    eRet = Download(url, false);
    if (IsntError(eRet))
    {
/*
        // This was segfaulting
        if (m_buffer)
        {
            _show_args2(m_bytesInBuffer,m_bufferSize);
            unsigned int i;
            cerr << "==" << endl;
            for(i=0; i < m_bytesInBuffer; i++)
            {
                if (0!=((char *)m_buffer)[i])
                    cerr << ((char *)m_buffer)[i];
                else
                    cerr << "NULL";
            }
            cerr << endl << "==" << endl;
            for(; i < m_bufferSize; i++)
            {
                if (0!=((char *)m_buffer)[i])
                    cerr << ((char *)m_buffer)[i];
                else
                    cerr << "NULL";
            }
            cerr << endl << "==" << endl;
        }
*/
        page = string((char *)m_buffer);
    }

    if (m_buffer)
    {
        _show_args1(m_buffer);
       delete m_buffer;
       m_buffer = NULL;
       _show_args1(m_buffer);
    }

    return eRet;
}

Error Http::DownloadToFile(const string &url, const string &destPath)
{
    Error eRet;

    m_destPath = destPath;
    eRet = Download(url, true);
    if (m_file)
    {
        fclose(m_file);
        m_file = NULL;
    }

    return eRet;
}

int Http::WriteToBuffer(unsigned char *buffer, unsigned int size)
{
    cerr << "WriteToBuffer " << size << endl << flush;
    if (m_buffer == NULL)
    {
        _you_are_here;
        m_bufferSize = kBufferSize;
        m_buffer = new unsigned char[m_bufferSize];
    }
    _show_args1(m_buffer);
    if (m_bytesInBuffer + size > m_bufferSize)
    {
        _you_are_here;
        unsigned char *pTemp;

        m_bufferSize += (kBufferSize > size) ? (kBufferSize) : (kBufferSize + size);
        pTemp = new unsigned char[m_bufferSize];
        if (m_bufferSize<m_bytesInBuffer)
        {
            exit(13);
        }
        memcpy(pTemp, m_buffer, m_bytesInBuffer);
        delete m_buffer;
        m_buffer = pTemp;
        _show_args1(m_buffer);
    }

    if (m_bufferSize < m_bytesInBuffer+size)
    {
        exit(13);
    }
    memcpy(m_buffer + m_bytesInBuffer, buffer, size);
    m_bytesInBuffer += size;

    return size;
}

int Http::WriteToFile(unsigned char *buffer, unsigned int size)
{
    _show_args4(buffer,size,m_bytesInBuffer,m_bufferSize);
    if (m_file == NULL)
    {
        m_file = fopen(m_destPath.c_str(), "wb");
        if (m_file == NULL)
            return -1;
    }

    return fwrite(buffer, sizeof(unsigned char), size, m_file);
}

Error Http::Download(const string &url, bool fileDownload)
{
    _show_args2(url,fileDownload);
    _show_args2(m_bufferSize,m_buffer);
    Error          result = kError_InvalidParam;
    char           hostname[kMaxHostNameLen + 1];
    char           localname[kMaxHostNameLen + 1];
    char           proxyname[kMaxURLLen + 1];
    unsigned short port;
    struct         sockaddr_in  addr;
    struct         hostent      host;
    SOCKET         s = -1;
    char*          file = NULL;
    bool           useProxy;
    unsigned int   bytesReceived = 0;

    result = kError_ProtocolNotSupported;

    // where should we connect to?
    if(!strncasecmp(url.c_str(), "http://", 7))
    {
        _show_args2(m_bufferSize,m_buffer);
        _nullChk(m_context);
        _nullChk(m_context->prefs);
        int32 numFields;
        uint32 length;

        result = kError_NoErr;  

        m_context->prefs->GetPrefBoolean(kUseProxyPref, &useProxy);

        length = sizeof(proxyname);
        m_context->prefs->GetPrefString(kProxyHostPref, proxyname, &length);
        _show_args2(m_bufferSize,m_buffer);
        if(useProxy)
        {
            numFields = sscanf(proxyname, 
                               "http://%[^:/]:%hu", hostname, &port);

            strncpy(proxyname, url.c_str(),length);
            file = proxyname;
        }
        else
        {
            numFields = sscanf(url.c_str(), 
                           "http://%[^:/]:%hu", hostname, &port);

            file = strchr(url.c_str() + 7, '/');
        }
        _show_args2(m_bufferSize,m_buffer);
        if(numFields < 1)
        {
            result = kError_InvalidURL;     
        }

        if(numFields < 2)
        {
            port = kHttpPort;
        }            
    }
    _show_args2(m_bufferSize,m_buffer);
    // get hostname
    if(IsntError(result))
    {
        struct hostent* hostByName=NULL;
        struct hostent  hostByIP;

        //*m_debug << "gethostbyname: " << hostname << endl;
        hostByName = gethostbyname(hostname);
        _nullChk(hostByName);
        _show_args2(m_bufferSize,m_buffer);
        // On some stacks a numeric IP address
        // will not parse with gethostbyname.  
        // If that didn't work try to convert it as a
        // numeric address before giving up.
        if(!hostByName)
        {
            _show_args2(m_bufferSize,m_buffer);
            static unsigned long ip;
            static char *addr_ptr[2] = {(char*)&ip, NULL};

            if((int)(ip = inet_addr(hostname)) < 0) 
                result =  kError_CantFindHost;
            else
            {
                hostByIP.h_length = sizeof(uint32);
                hostByIP.h_addrtype = AF_INET;
                hostByIP.h_addr_list = (char**)&addr_ptr;
                hostByName = &hostByIP;
            }
        }
        _show_args2(m_bufferSize,m_buffer);
        if(IsntError(result))
        {
            memcpy(&host, hostByName, sizeof(struct hostent));
        }
    }
    _show_args2(m_bufferSize,m_buffer);
    // open socket
    if(IsntError(result))
    {
        memset(&addr, 0x00, sizeof(struct sockaddr_in));
        _show_args2(m_bufferSize,m_buffer);
        int temp=sizeof(struct sockaddr_in);
        if (temp < host.h_length)
        {
            exit(13);
        }
        memcpy(&addr.sin_addr, host.h_addr, host.h_length);
        _show_args2(m_bufferSize,m_buffer);
        addr.sin_family= host.h_addrtype;
        addr.sin_port= htons(port); 

        //*m_debug << "socket" << endl;

        s = socket(host.h_addrtype, SOCK_STREAM, 0);
        _show_args2(m_bufferSize,m_buffer);
        if(s < 0)
            result = kError_CantCreateSocket;
    }
    _show_args2(m_bufferSize,m_buffer);
    // connect and send request
    if(IsntError(result))
    {
        Error err;
        int   ret;
        
        err = Connect(s, (struct sockaddr*)&addr, ret);
        _show_args1((long int)result);
        if (IsError(err))
            result = kError_UserCancel;
            
        if (ret < 0)    
            result = kError_ConnectFailed;
        _show_args2(m_bufferSize,m_buffer);
        if(IsntError(result))
        {
            gethostname(localname, kMaxHostNameLen);    
            _show_args2(m_bufferSize,m_buffer);
            const char* kHTTPQuery = "GET %s HTTP/1.1\r\n"
                                     "Host: %s\r\n"
                                     "Accept: */*\r\n" 
                                     "User-Agent: FreeAmp/%s\r\n\r\n";

            // the magic 256 is enough for a time field that
            // we got from the server
            size_t sizeof_query=strlen(kHTTPQuery)+strlen(file)+
                strlen(localname)+strlen(FREEAMP_VERSION)+2;
            int snprintf_return=0;
            _show_args1(sizeof_query);
            char* query = new char[sizeof_query];
            _show_args2(m_bufferSize,m_buffer);
            snprintf_return=snprintf(query, sizeof_query,kHTTPQuery, file, localname, 
FREEAMP_VERSION);
            _show_args2(m_bufferSize,m_buffer);
            if (0>=snprintf_return)
            {
                exit(13);
            }
            if (strlen(query)>=sizeof_query)
            {
                exit(13);
            }
            int count;

            err = Send(s, query, strlen(query), 0, count);
            if (IsError(err))
                result = kError_UserCancel; 

            if(count != (int)strlen(query))
            {
                result = kError_IOError;
            }

            delete [] query;
            query=NULL;
        }
    }
    _show_args2(m_bufferSize,m_buffer);
    // receive response
    if(IsntError(result))
    {
        uint32 bufferSize = 2048;
        char* buffer = NULL;
        int count;
        uint32 total = 0;

        buffer = (char*)malloc(bufferSize);
        _show_args2(m_bufferSize,m_buffer);
        result = kError_OutOfMemory;

        if(buffer)
        {
            Error err;
            result = kError_NoErr;

            do
            {
                _show_args2(m_bufferSize,m_buffer);
                if(total >= bufferSize - 1)
                {
                    bufferSize *= 2;

                    buffer = (char*) realloc(buffer, bufferSize);

                    if(!buffer)
                    {
                        result = kError_OutOfMemory;
                        break;
                    }
                }
                _show_args2(m_bufferSize,m_buffer);
                err = Recv(s, buffer + total, bufferSize - total - 1, 0, count);
                _show_args2(m_bufferSize,m_buffer);
                if (IsError(err))
                    result = kError_UserCancel;

                if(count > 0)
                    total += count;
                else
                {
                    result = kError_IOError;
                }

            }while(IsntError(result) && !IsHTTPHeaderComplete(buffer, total));
        }
        _show_args2(m_bufferSize,m_buffer);
        // parse header
        if(IsntError(result))
        {
            uint32 returnCode = atoi(buffer+9);
            buffer[total] = 0x00;
            cout << buffer << endl;

            cout << returnCode << endl;
            _show_args2(m_bufferSize,m_buffer);
            switch(buffer[9])
            {
                // 1xx: Informational - Request received, continuing process
                case '1':
                {
                    _you_are_here;
                    // not sure what to do here... continue receiving???
                }    

                // 2xx: Success - The action was successfully received,
                // understood, and accepted
                case '2':
                {
                    _show_args2(m_bufferSize,m_buffer);
                    Error err;
                    result = kError_UnknownErr;

                    int32 fileSize = GetContentLengthFromHeader(buffer);
                    _show_args2(m_bufferSize,m_buffer);

                    result = kError_NoErr;
                    int wcount = 0;

                    char* cp;

                    cp = strstr(buffer, "\r\n\r\n");
                    _show_args2(m_bufferSize,m_buffer);
                    if(cp)
                        cp += 4;
                    if(cp)
                    {
                        if(cp - buffer < (int)total)
                        {
                            _show_args2(m_bufferSize,m_buffer);
                            _show_args3(fileDownload,(unsigned char 
*)cp,total-(cp-buffer));
                            if (fileDownload)
                            {
                                _show_args1(wcount);
                                wcount = this->Http::WriteToFile((unsigned char *)cp,
                                                     total - (cp - buffer));
                                _show_args1(wcount);
                            }
                            else
                            {
                                _show_args1(wcount);
                                _show_args3(m_bufferSize,m_bytesInBuffer,m_buffer);
                                wcount = this->Http::WriteToBuffer((unsigned char *)cp,
                                                       total - (cp-buffer));
                                _show_args1(wcount);
                                _show_args3(m_bufferSize,m_bytesInBuffer,m_buffer);
                            }
                            bytesReceived = total - (cp - buffer);
                            _show_args1(bytesReceived);
                        }
                    }

                    do
                    {
                        if (min(bufferSize, fileSize - bytesReceived) != 0)
                                                {
                                                        err = Recv(s, buffer,
                                                                        
min(bufferSize, fileSize - bytesReceived),
                                                                        0, count);
                                                }
                                                else
                                                        count = 0;
                        if (IsError(err))
                            result = kError_UserCancel;
                        else
                           if(count > 0)
                           {
                               _you_are_here;
                               if (fileDownload)
                               {
                                   _show_args2((unsigned char *)buffer,count);
                                  wcount = WriteToFile((unsigned char *)buffer,
                                                       (unsigned int)count);
                                  _show_args1(wcount);
                               }
                               else
                               {
                                   _show_args2((unsigned char *)buffer,count);
                                  wcount = WriteToBuffer((unsigned char *)buffer
,
                                                       (unsigned int)count);
                                  _show_args1(wcount);
                                  _show_args3(m_bufferSize,m_bytesInBuffer,m_buffer);
                               }
                               bytesReceived += count;
                               _show_args1(bytesReceived);
                               Progress(bytesReceived, fileSize);
                           }

                        if(count < 0)
                            result = kError_IOError;

                        if(wcount < 0)
                            result = kError_WriteFile;

                    }while(count > 0 && IsntError(result) &&
                           !m_exit && wcount >= 0 &&
                           (int)bytesReceived != fileSize);

                break;   
                }

                // 3xx: Redirection - Further action must be taken in order to
                // complete the request
                case '3':
                {
                    _you_are_here;
                    char* cp = strstr(buffer, "Location:");
                    //int32 length;

                    if(cp)
                    {
                        cp += 9;

                        if(*cp == 0x20)
                            cp++;

                        char *end;
                        for(end = cp; end < buffer + total; end++)
                            if(*end=='\r' || *end == '\n') break;

                        *end = 0x00;

                        if (305 == returnCode) // proxy
                        {
                            size_t sizeof_proxy=strlen(cp) + strlen(url.c_str()) + 1;
                            char* proxy = new char[sizeof_proxy];

                            snprintf(proxy, sizeof_proxy, "%s%s", cp, url.c_str());

                            result = Download(string(proxy), fileDownload);
                            delete [] proxy;
                            proxy=NULL;
                        }
                        else // redirect of some type
                        {
                            result = Download(string(cp), fileDownload);
                        }
                    }
                    
                    break;
                }

                // 4xx: Client Error - The request contains bad syntax or cannot
                // be fulfilled
                case '4':
                {
                    _you_are_here;
                    switch(returnCode)
                    {
                        case 400:
                            result = kError_BadHTTPRequest;
                            break;

                        case 401:
                            result = kError_AccessNotAuthorized;
                            break;                           

                        case 403:
                            result = kError_DownloadDenied;
                            break;

                        case 404:
                            result = kError_HTTPFileNotFound;
                            break;

                        default:
                            result = kError_UnknownErr;
                            break;
                    }

                    break;
                }

                // 5xx: Server Error - The server failed to fulfill an apparently
                // valid request
                case '5':
                {
                    _you_are_here;
                    result = kError_UnknownServerError;
                    break;
                }
                default:
                {
                    _you_are_here;
                }
            }
        }
        _show_args1((long int)result);
        // cleanup
        if(buffer) {
            free(buffer);            
            buffer=NULL;
        }
    }
    _show_args1(s);
    // cleanup
    if(s > 0)
        closesocket(s);

    _show_args2((long int)result,"end func\n");
    return result;
}

Error Http::Connect(int hHandle, const sockaddr *pAddr, int &iRet)
{
    fd_set              sSet; 
    struct timeval      sTv;

#if defined(WIN32)
        unsigned long lMicrosoftSucksBalls = 1;
        ioctlsocket(hHandle, FIONBIO, &lMicrosoftSucksBalls);
#elif defined(__BEOS__)
//      int on = 1;
//      setsockopt( hHandle, SOL_SOCKET, SO_NONBLOCK, &on, sizeof( on ) );
#else
    fcntl(hHandle, F_SETFL, fcntl(hHandle, F_GETFL) | O_NONBLOCK);
#endif

    iRet = connect(hHandle, (const sockaddr *)pAddr,sizeof(*pAddr));
#ifndef WIN32
    if (iRet == -1 && errno != EINPROGRESS)
       return kError_NoErr;
#endif  
    for(; iRet && !m_exit;)
    {
        sTv.tv_sec = 0; sTv.tv_usec = 0;
        FD_ZERO(&sSet); FD_SET(hHandle, &sSet);
        iRet = select(hHandle + 1, NULL, &sSet, NULL, &sTv);
        if (!iRet)
        {
           usleep(100000);
           continue;
        }

        if (iRet < 0)
           return kError_NoErr;
           
        break;
    }
    
    if (m_exit)
       return kError_Interrupt;
       
    return kError_NoErr;
}

Error Http::Recv(int hHandle, char *pBuffer, int iSize, 
                 int iFlags, int &iRead)
{
    _show_args2(m_bufferSize,m_buffer);
    fd_set              sSet; 
    struct timeval      sTv;
    int                 iRet;

    iRead = 0;
    for(; !m_exit;)
    {
        sTv.tv_sec = 0; sTv.tv_usec = 0;
        FD_ZERO(&sSet); FD_SET(hHandle, &sSet);
        iRet = select(hHandle + 1, &sSet, NULL, NULL, &sTv);
        if (!iRet)
        {
           usleep(10000);
           continue;
        }
        _show_args2(m_bufferSize,m_buffer);
        iRead = recv(hHandle, pBuffer, iSize, iFlags);
        _show_args2(m_bufferSize,m_buffer);
        if (iRead < 0)
        {
           return kError_NoErr;
        }
        break;
    }
    _show_args2(m_bufferSize,m_buffer);
    if (m_exit)
       return kError_Interrupt;
       
    return kError_NoErr;
}                            

Error Http::Send(int hHandle, char *pBuffer, int iSize, 
                 int iFlags, int &iRead)
{
    fd_set              sSet; 
    struct timeval      sTv;
    int                 iRet;

    iRead = 0;
    for(; !m_exit;)
    {
        sTv.tv_sec = 0; sTv.tv_usec = 0;
        FD_ZERO(&sSet); FD_SET(hHandle, &sSet);
        iRet = select(hHandle + 1, NULL, &sSet, NULL, &sTv);
        if (!iRet)
        {
                   usleep(10000);
           continue;
        }
        iRead = send(hHandle, pBuffer, iSize, iFlags);
        if (iRead < 0)
        {
           return kError_NoErr;
        }
        break;
    }

    if (m_exit)
       return kError_Interrupt;
       
    return kError_NoErr;
}                            

void Http::Progress(unsigned int bytesReceived, unsigned int maxBytes)
{

}

bool Http::IsHTTPHeaderComplete(char* buffer, uint32 length)
{
    bool result = false;

    for(char* cp = buffer; cp < buffer + length; cp++)
    {
        if(!strncmp(cp, "\n\n", 2) || !strncmp(cp, "\r\n\r\n", 4))
        {
            result = true;
            break;
        }
    }

    return result;
}

int32 Http::GetContentLengthFromHeader(const char* buffer)
{
    int32 result = -1;

    char* cp = strstr(buffer, "Content-Length:");

    if(cp)
    {
        cp += strlen("Content-Length:") + 1;

        result = atoi(cp);
    }

    return result;
} 

Reply via email to