Web CGI Upload a File

804 views
Skip to first unread message

clipper6

unread,
Jan 29, 2014, 2:12:53 AM1/29/14
to harbou...@googlegroups.com
I'm trying to develop a CGI app in harbour. One of it's feature is to allow user to upload a document. How do I handle this in CGI Harbour? I found this topic in perl but don't know how to translate this in Harbour. Please help. http://www.sitepoint.com/uploading-files-cgi-perl/

DaNiEl MaXiMiLiAnO

unread,
Jan 29, 2014, 5:20:18 AM1/29/14
to harbou...@googlegroups.com
Hi Clipper6

C:\Hb32\contrib\hbtip\cgi.prg


 
Saludos
                DaNIEl MaXiMiLiAnO


El día miércoles, 29 de enero de 2014 4:12, clipper6 <arl...@gmail.com> escribió:
I'm trying to develop a CGI app in harbour. One of it's feature is to allow user to upload a document. How do I handle this in CGI Harbour? I found this topic in perl but don't know how to translate this in Harbour. Please help. http://www.sitepoint.com/uploading-files-cgi-perl/
--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users
 
---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


clipper6

unread,
Jan 29, 2014, 7:49:56 PM1/29/14
to harbou...@googlegroups.com, DaNiEl MaXiMiLiAnO
I found cgi.prg in this location C:\hb32\contrib\hbgd\tests. Is this the same?

clipper6

unread,
Jan 29, 2014, 8:01:29 PM1/29/14
to harbou...@googlegroups.com, DaNiEl MaXiMiLiAnO
I tried compiling but I'm getting this:

c:\hbmk2 cgi.prg
hbmk2: Processing local make script: hbmk.hbm
Harbour 3.2.0dev (r1309161336)
Copyright (c) 1999-2013, http://harbour-project.org/
Compiling 'cgi.prg'...
cgi.prg(190) Error E0014  #endif does not match #ifdef
cgi.prg(192) Error E0014  #endif does not match #ifdef
cgi.prg(206) Error E0014  #endif does not match #ifdef
cgi.prg(217) Error E0014  #endif does not match #ifdef
4 errors

Please help.


On Wednesday, January 29, 2014 6:20:18 PM UTC+8, DaNiElMaXiMiLiAnO wrote:

clipper6

unread,
Jan 29, 2014, 8:20:46 PM1/29/14
to harbou...@googlegroups.com, DaNiEl MaXiMiLiAnO
I also tried compiling counter.prg and it compiled but when I ran it there was and error: bgd.dll missing. Where can I get this dll?
This is the path: C:\hb32\contrib\hbgd\tests

elch

unread,
Jan 29, 2014, 8:41:34 PM1/29/14
to harbou...@googlegroups.com, DaNiEl MaXiMiLiAnO
Hi,

hbgd is a GRAPHICs lib - maybe not what you are searching for ...
see www.libgd.org

regards

DaNiEl MaXiMiLiAnO

unread,
Jan 30, 2014, 7:24:52 AM1/30/14
to harbou...@googlegroups.com
Hi Clipper6 :
in C:\hb32\contrib\hbgd\doc

HBGD is basically a wrapper of Thomas Boutell's GD Library version 2.0.33.
      GD Library is a powerfull graphic library very usefull expecially under CGI environment.

      HBGD actually contains almost all GD functions, more a set of functions that extends original
      library and a set of classes that make easier to work with this library.

      Thomas Boutell's GD library actually supports these graphic formats:
      PNG, JPEG, GIF, Animated GIF, GD, GD2, WBMP, XBM, XPM
      WBMP is Wireless Bitmap, not Windows Bitmap, and it is used for WAP. It is a B&W bitmap.

      HBGD actually supports PNG, JPEG, GIF, GD, WBMP
      The other Animated GIF, GD2, XBM and XPM are not wrapped actually.

      Using this library you can, as a little example:
      - create an image in memory, true color or with a 256 colors palette;
      - load and save an image of above formats and convert it to another supported format;
      - draw dots, lines, dashed lines, polygons, rectangles, arcs, circles and ellipses;
      - fill with colors;
      - draw with brushes;
 
Saludos
                DaNIEl MaXiMiLiAnO

Massimo Belgrano

unread,
Jan 30, 2014, 12:40:58 PM1/30/14
to harbou...@googlegroups.com
CGI.prg Seem not included in hb32(nigtly)


/*
 * xHarbour Project source code:
 * TIPCgi Class oriented cgi protocol
 *
 * Copyright 2006 Lorenzo Fiorini <lorenzo...@gmail.com>
 *
 * code from:
 * TIP Class oriented Internet protocol library
 *
 * Copyright 2003 Giancarlo Niccolai <gi...@niccolai.ws>
 *
 *    CGI Session Manager Class
 *
 * Copyright 2003-2006 Francesco Saverio Giudice <info / at / fsgiudice / dot / 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, 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 software; see the file COPYING.txt.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
 *
 * As a special exception, the Harbour Project gives permission for
 * additional uses of the text contained in its release of Harbour.
 *
 * The exception is that, if you link the Harbour libraries with other
 * files to produce an executable, this does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * Your use of that executable is in no way restricted on account of
 * linking the Harbour library code into it.
 *
 * This exception does not however invalidate any other reasons why
 * the executable file might be covered by the GNU General Public License.
 *
 * This exception applies only to the code released by the Harbour
 * Project under the name Harbour.  If you copy code from other
 * Harbour Project or Free Software Foundation releases into a copy of
 * Harbour, as the General Public License permits, the exception does
 * not apply to the code that you add in this way.  To avoid misleading
 * anyone as to the status of such modified files, you must delete
 * this exception notice from them.
 *
 * If you write modifications of your own for Harbour, it is your choice
 * whether to permit this exception to apply to your modifications.
 * If you do not wish that, delete this exception notice.
 *
 */

#include "hbclass.ch"

#include "fileio.ch"

#define CGI_IN  0
#define CGI_OUT 1
#define _CRLF Chr( 13 ) + Chr( 10 )
#define _BR "<br />"

CREATE CLASS TIPCgi

   VAR HTTP_RAW_POST_DATA

   VAR cCgiHeader
   VAR cHtmlPage
   VAR hGets        INIT { => }
   VAR hPosts       INIT { => }
   VAR hCookies     INIT { => }
   VAR hSession     INIT { => }
   VAR bSavedErrHandler
   VAR cSessionSavePath
   VAR cSID
   VAR cDumpSavePath
   VAR lDumpHtml    INIT .F.
   VAR Cargo

   METHOD New()
   METHOD Header( cValue )
   METHOD Redirect( cUrl )
   METHOD Write( cString )
   METHOD Flush()
   METHOD ErrHandler( xError )

   METHOD StartHtml( hOptions )
   METHOD EndHtml()
   METHOD SaveHtmlPage( cFile )

   METHOD StartSession( cSID )
   METHOD DestroySession( cID )
   METHOD CreateSID( cCRCKey ) INLINE ::cSID := tip_GenerateSID( cCrcKey )
   METHOD CheckCrcSID( cSID, cCRCKey ) INLINE tip_CheckSID( cSID, cCRCKey )
   METHOD SessionEncode()
   METHOD SessionDecode( cData )

ENDCLASS

METHOD New() CLASS TIPCgi

   LOCAL aTemp
   LOCAL aVar
   LOCAL lPost
   LOCAL nCount
   LOCAL nLen
   LOCAL nRead
   LOCAL cTemp

   ::bSavedErrHandler := ErrorBlock( {| e | ::ErrHandler( e ) } )

   ::cCgiHeader := ""
   ::cHtmlPage := ""

   lPost := ( "POST" $ Upper( GetEnv( "REQUEST_METHOD" ) ) )
   IF lPost
      nLen := Val( GetEnv( "CONTENT_LENGTH" ) )
      cTemp := Space( nLen )
      IF ( ( nRead := FRead( CGI_IN, @cTemp, nLen ) ) != nLen )
         ::ErrHandler( "post error read " + hb_ntos( nRead ) + " instead of " + hb_ntos( nLen ) )
      ELSE
         ::HTTP_RAW_POST_DATA := cTemp
         aTemp := hb_ATokens( cTemp, "&" )
         nLen := Len( aTemp )
         IF nLen > 0
            FOR nCount := 1 TO nLen
               aVar := hb_ATokens( aTemp[ nCount ], "=" )
               IF Len( aVar ) == 2
                  ::hPosts[ AllTrim( tip_URLDecode( aVar[ 1 ] ) ) ] := tip_URLDecode( aVar[ 2 ] )
               ENDIF
            NEXT
         ENDIF
      ENDIF
   ELSE
      cTemp := GetEnv( "QUERY_STRING" )
      IF ! Empty( cTemp )
         aTemp := hb_ATokens( cTemp, "&" )
         nLen := Len( aTemp )
         IF nLen > 0
            FOR nCount := 1 TO nLen
               aVar := hb_ATokens( aTemp[ nCount ], "=" )
               IF Len( aVar ) == 2
                  ::hGets[ AllTrim( tip_URLDecode( aVar[ 1 ] ) ) ] := tip_URLDecode( aVar[ 2 ] )
               ENDIF
            NEXT
         ENDIF
      ENDIF
   ENDIF

   cTemp := GetEnv( "HTTP_COOKIE" )
   IF ! Empty( cTemp )
      aTemp := hb_ATokens( cTemp, ";" )
      nLen := Len( aTemp )
      IF nLen > 0
         FOR nCount := 1 TO nLen
            aVar := hb_ATokens( aTemp[ nCount ], "=" )
            IF Len( aVar ) == 2
               ::hCookies[ AllTrim( tip_URLDecode( aVar[ 1 ] ) ) ] := tip_URLDecode( aVar[ 2 ] )
            ENDIF
         NEXT
      ENDIF
   ENDIF

   RETURN Self

METHOD Header( cValue ) CLASS TIPCgi

   IF Empty( cValue )
      ::cCgiHeader += "Content-Type: text/html" + _CRLF
   ELSE
      ::cCgiHeader += cValue + _CRLF
   ENDIF

   RETURN Self

METHOD Redirect( cUrl ) CLASS TIPCgi

   ::cCgiHeader += "Location: " + cUrl + _CRLF

   RETURN Self

METHOD Flush() CLASS TIPCgi

   LOCAL cStream
   LOCAL lRet

   LOCAL nH
   LOCAL cFile

   LOCAL cSID := ::cSID
   LOCAL cSession

   hb_HEval( ::hCookies, {| k, v | ::cCgiHeader += "Set-Cookie: " + k + "=" + v + ";" + _CRLF } )

   cStream := ::cCgiHeader + _CRLF + ::cHtmlPage + _CRLF

   lRet := ( FWrite( CGI_OUT, cStream ) == hb_BLen( cStream ) )

   IF ::lDumpHtml
      IF Empty( ::cDumpSavePath )
         ::cDumpSavePath := hb_DirTemp()
      ENDIF
      IF ( nH := FCreate( ::cDumpSavePath + "dump.html", FC_NORMAL ) ) != F_ERROR
         FWrite( nH, ::cHtmlPage )
      ENDIF
      FClose( nH )
   ENDIF

   ::cCgiHeader := ""
   ::cHtmlPage := ""

   IF ! Empty( cSID )

      cFile := ::cSessionSavePath + "SESSIONID_" + cSID

      IF ( nH := FCreate( cFile, FC_NORMAL ) ) != F_ERROR
         cSession := ::SessionEncode()
         IF FWrite( nH, cSession ) != hb_BLen( cSession )
            ::Write( "ERROR: On writing session file : " + cFile + ", File error : " + hb_CStr( FError() ) )
         ENDIF
         FClose( nH )
      ELSE
         ::Write( "ERROR: On writing session file : " + cFile + ", File error : " + hb_CStr( FError() ) )
      ENDIF
   ENDIF

   RETURN lRet

METHOD SaveHtmlPage( cFile ) CLASS TIPCgi

   LOCAL nFile
   LOCAL lSuccess
   LOCAL cStream

   nFile := FCreate( cFile )

   IF nFile != F_ERROR
      cStream := ::cHtmlPage + _CRLF
      lSuccess := ( FWrite( nFile, cStream ) == hb_BLen( cStream ) )
      FClose( nFile )
   ELSE
      lSuccess := .F.
   ENDIF

   RETURN lSuccess

METHOD StartSession( cSID ) CLASS TIPCgi

   LOCAL nH
   LOCAL cFile
   LOCAL nFileSize
   LOCAL cBuffer

   IF Empty( cSID )

      IF ( nH := hb_HPos( ::hGets, "SESSIONID" ) ) != 0
         cSID := hb_HValueAt( ::hGets, nH )
      ELSEIF ( nH := hb_HPos( ::hPosts, "SESSIONID" ) ) != 0
         cSID := hb_HValueAt( ::hPosts, nH )
      ELSEIF ( nH := hb_HPos( ::hCookies, "SESSIONID" ) ) != 0
         cSID := hb_HValueAt( ::hCookies, nH )
      ENDIF

   ENDIF

   IF Empty( ::cSessionSavePath )
      ::cSessionSavePath := hb_DirTemp()
   ENDIF

   IF ! Empty( cSID )

      ::cSID := cSID

      cFile := ::cSessionSavePath + "SESSIONID_" + cSID

      IF hb_FileExists( cFile )
         IF ( nH := FOpen( cFile, FO_READ ) ) != F_ERROR
            nFileSize := FSeek( nH, 0, FS_END )
            FSeek( nH, 0, FS_SET )
            cBuffer := Space( nFileSize )
            IF ( FRead( nH, @cBuffer, nFileSize ) ) != nFileSize
               ::ErrHandler( "ERROR: On reading session file : " + cFile + ", File error : " + hb_CStr( FError() ) )
            ELSE
               ::SessionDecode( cBuffer )
            ENDIF
            FClose( nH )
         ENDIF
      ELSE
         ::ErrHandler( "ERROR: On opening session file : " + cFile + ", file not exist." )
      ENDIF

   ELSE

      ::CreateSID()
      ::hSession := { => }

   ENDIF

   ::hCookies[ "SESSIONID" ] := ::cSID

   RETURN Self

METHOD SessionEncode() CLASS TIPCgi

   RETURN hb_Serialize( ::hSession )

METHOD SessionDecode( cData ) CLASS TIPCgi

   ::hSession := hb_Deserialize( cData )

   RETURN HB_ISHASH( ::hSession )

METHOD DestroySession( cID ) CLASS TIPCgi

   LOCAL cFile
   LOCAL cSID := ::cSID
   LOCAL lRet

   IF ! Empty( cID )
      cSID := cID
   ENDIF

   IF ! Empty( cSID )

      ::hSession := { => }

      cFile := ::cSessionSavePath + "SESSIONID_" + cSID

      IF !( lRet := ( FErase( cFile ) == 0 ) )
         ::Write( "ERROR: On deleting session file : " + cFile + ", File error : " + hb_CStr( FError() ) )
      ELSE
         ::hCookies[ "SESSIONID" ] := cSID + "; expires= " + tip_DateToGMT( Date() - 1 )
         ::CreateSID()
         cSID := ::cSID
         ::hCookies[ "SESSIONID" ] := cSID
      ENDIF

   ENDIF

   RETURN lRet

METHOD ErrHandler( xError ) CLASS TIPCgi

   LOCAL nCalls
   LOCAL cErrMsg := ""

   cErrMsg += '<table border="1">'

   cErrMsg += "<tr><td>SCRIPT NAME:</td><td>" + GetEnv( "SCRIPT_NAME" ) + "</td></tr>"

   IF HB_ISOBJECT( xError )
      cErrMsg += "<tr><td>CRITICAL ERROR:</td><td>" + xError:Description + "</td></tr>"
      cErrMsg += "<tr><td>OPERATION:</td><td>" + xError:Operation + "</td></tr>"
      cErrMsg += "<tr><td>OS ERROR:</td><td>" + hb_ntos( xError:OsCode ) + " IN " + xError:SubSystem + "/" + hb_ntos( xError:SubCode ) + "</td></tr>"
      cErrMsg += "<tr><td>FILENAME:</td><td>" + Right( xError:FileName, 40 ) + "</td></tr>"
   ELSEIF HB_ISSTRING( xError )
      cErrMsg += "<tr><td>ERROR MESSAGE:</td><td>" + tip_HtmlSpecialChars( xError ) + "</td></tr>"
   ENDIF

   nCalls := 1
   DO WHILE ! Empty( ProcName( nCalls ) )
      cErrMsg += "<tr><td>PROC/LINE:</td><td>" + ProcName( nCalls ) + "/" + hb_ntos( ProcLine( nCalls ) ) + "</td></tr>"
      nCalls++
   ENDDO

   cErrMsg += "</table>"

   ::Write( cErrMsg )

   OutErr( cErrMsg )

   ::Flush()

   QUIT

   RETURN NIL

METHOD Write( cString ) CLASS TIPCgi

   ::cHtmlPage += cString + _CRLF

   RETURN Self

METHOD StartHtml( hOptions ) CLASS TIPCgi

   ::cHtmlPage += ;
      '<?xml version="1.0"' + HtmlOption( hOptions, "encoding", " " ) + "?>" + _CRLF + ;
      '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' + _CRLF + ;
      '<html xmlns="http://www.w3.org/1999/xhtml">' + ;
      "<head>" + ;
      HtmlTag( hOptions, "title", "title" ) + ;
      HtmlScript( hOptions ) + ;
      HtmlStyle( hOptions ) + ;
      HtmlLinkRel( hOptions ) + ;
      "</head>" + ;
      "<body " + ;
      HtmlAllOption( hOptions ) + ;
      ">"

   RETURN Self

METHOD EndHtml() CLASS TIPCgi

   ::cHtmlPage += "</body></html>"

   RETURN Self

STATIC FUNCTION HtmlTag( xVal, cKey, cDefault )

   LOCAL cVal := ""

   hb_default( @cDefault, "" )

   IF ! Empty( xVal ) .AND. ! Empty( cKey )
      IF hb_HHasKey( xVal, cKey )
         cVal := xVal[ cKey ]
         hb_HDel( xVal, cKey )
      ENDIF
   ENDIF

   IF cVal == ""
      cVal := cDefault
   ENDIF

   IF !( cVal == "" )
      cVal := "<" + cKey + ">" + cVal + "</" + cKey + ">"
   ENDIF

   RETURN cVal

/*
STATIC FUNCTION HtmlAllTag( hTags, cSep )

   LOCAL cVal := ""

   hb_default( @cSep, " " )

   hb_HEval( hTags, {| k | cVal += HtmlTag( hTags, k ) + cSep } )

   RETURN cVal
*/

STATIC FUNCTION HtmlOption( xVal, cKey, cPre, cPost, lScan )

   LOCAL cVal := ""

   IF ! Empty( xVal )
      IF Empty( cKey )
         cVal := xVal
      ELSEIF hb_HHasKey( xVal, cKey )
         cVal := xVal[ cKey ]
         IF Empty( lScan )
            hb_HDel( xVal, cKey )
         ENDIF
         cVal := cKey + '="' + cVal + '"'
         IF cPre != NIL
            cVal := cPre + cVal
         ENDIF
         IF cPost != NIL
            cVal := cVal + cPost
         ENDIF
      ENDIF
   ENDIF

   RETURN cVal

STATIC FUNCTION HtmlAllOption( hOptions, cSep )

   LOCAL cVal := ""

   IF ! Empty( hOptions )
      hb_default( @cSep, " " )

      hb_HEval( hOptions, {| k | cVal += HtmlOption( hOptions, k,,, .T. ) + cSep } )
   ENDIF

   RETURN cVal

/*
STATIC FUNCTION HtmlValue( xVal, cKey, cDefault )

   LOCAL cVal := ""

   hb_default( @cDefault, "" )

   IF ! Empty( xVal ) .AND. ! Empty( cKey )
      IF hb_HHasKey( xVal, cKey )
         cVal := xVal[ cKey ]
         hb_HDel( xVal, cKey )
      ENDIF
   ENDIF

   IF cVal == ""
      cVal := cDefault
   ENDIF

   RETURN cVal

STATIC FUNCTION HtmlAllValue( hValues, cSep )

   LOCAL cVal := ""

   IF ! Empty( hValues )
      hb_default( @cSep, " " )

      hb_HEval( hValues, {| k | cVal += HtmlValue( hValues, k ) + cSep } )
   ENDIF

   RETURN cVal
*/

STATIC FUNCTION HtmlScript( hVal, cKey )

   LOCAL hTmp
   LOCAL cRet := ""
   LOCAL cVal
   LOCAL nPos
   LOCAL cTmp

   hb_default( @cKey, "script" )

   IF ! Empty( hVal )
      IF ( nPos := hb_HPos( hVal, cKey ) ) != 0
         hTmp := hb_HValueAt( hVal, nPos )
         IF HB_ISHASH( hTmp )
            IF ( nPos := hb_HPos( hTmp, "src" ) ) != 0
               cVal := hb_HValueAt( hTmp, nPos )
               IF HB_ISSTRING( cVal )
                  cVal := { cVal }
               ENDIF
               IF HB_ISARRAY( cVal )
                  cTmp := ""
                  AScan( cVal, {| cFile | cTmp += '<script src="' + cFile + '" type="text/javascript"></script>' + _CRLF } )
                  cRet += cTmp
               ENDIF
            ENDIF
            IF ( nPos := hb_HPos( hTmp, "var" ) ) != 0
               cVal := hb_HValueAt( hTmp, nPos )
               IF HB_ISSTRING( cVal )
                  cVal := { cVal }
               ENDIF
               IF HB_ISARRAY( cVal )
                  cTmp := ""
                  AScan( cVal, {| cVar | cTmp += cVar } )
                  cRet += '<script type="text/javascript">' + _CRLF + "<!--" + _CRLF + cTmp + _CRLF + "-->" + _CRLF + "</script>" + _CRLF
               ENDIF
            ENDIF
         ENDIF
         hb_HDel( hVal, cKey )
      ENDIF
   ENDIF

   RETURN cRet

STATIC FUNCTION HtmlStyle( hVal, cKey )

   LOCAL hTmp
   LOCAL cRet := ""
   LOCAL cVal
   LOCAL nPos
   LOCAL cTmp

   hb_default( @cKey, "style" )

   IF ! Empty( hVal )
      IF ( nPos := hb_HPos( hVal, cKey ) ) != 0
         hTmp := hb_HValueAt( hVal, nPos )
         IF HB_ISHASH( hTmp )
            IF ( nPos := hb_HPos( hTmp, "src" ) ) != 0
               cVal := hb_HValueAt( hTmp, nPos )
               IF HB_ISSTRING( cVal )
                  cVal := { cVal }
               ENDIF
               IF HB_ISARRAY( cVal )
                  cTmp := ""
                  AScan( cVal, {| cFile | cTmp += '<link rel="StyleSheet" href="' + cFile + '" type="text/css">' + _CRLF } )
                  cRet += cTmp
               ENDIF
            ENDIF
            IF ( nPos := hb_HPos( hTmp, "var" ) ) != 0
               cVal := hb_HValueAt( hTmp, nPos )
               IF HB_ISSTRING( cVal )
                  cVal := { cVal }
               ENDIF
               IF HB_ISARRAY( cVal )
                  cTmp := ""
                  AScan( cVal, {| cVar | cTmp += cVar } )
                  cRet += '<style type="text/css">' + _CRLF + "<!--" + _CRLF + cTmp + _CRLF + "-->" + _CRLF + "</style>" + _CRLF
               ENDIF
            ENDIF
         ENDIF
         hb_HDel( hVal, cKey )
      ENDIF
   ENDIF

   RETURN cRet

STATIC FUNCTION HtmlLinkRel( hVal, cKey )

   LOCAL hTmp
   LOCAL cRet := ""
   LOCAL cVal
   LOCAL nPos
   LOCAL cTmp

   hb_default( @cKey, "link" )

   IF ! Empty( hVal )
      IF ( nPos := hb_HPos( hVal, cKey ) ) != 0
         hTmp := hb_HValueAt( hVal, nPos )
         IF HB_ISHASH( hTmp )
            IF ( nPos := hb_HPos( hTmp, "rel" ) ) != 0
               cVal := hb_HValueAt( hTmp, nPos )
               IF HB_ISSTRING( cVal )
                  cVal := { cVal, cVal }
               ENDIF
               IF HB_ISARRAY( cVal )
                  cTmp := ""
                  AScan( cVal, {| aVal | cTmp += '<link rel="' + aVal[ 1 ] + '" href="' + aVal[ 2 ] + '"/>' + _CRLF } )
                  cRet += cTmp
               ENDIF
            ENDIF
         ENDIF
         hb_HDel( hVal, cKey )
      ENDIF
   ENDIF

   RETURN cRet



2014-01-29 clipper6 <arl...@gmail.com>:
I'm trying to develop a CGI app in harbour. One of it's feature is to allow user to upload a document. How do I handle this in CGI Harbour? I found this topic in perl but don't know how to translate this in Harbour. Please help. http://www.sitepoint.com/uploading-files-cgi-perl/

--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users
 
---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Massimo Belgrano
Delta Informatica S.r.l. (Cliccami per scoprire 

Lorenzo Fiorini

unread,
Jan 31, 2014, 12:00:37 PM1/31/14
to harbou...@googlegroups.com
On Wed, Jan 29, 2014 at 8:12 AM, clipper6 <arl...@gmail.com> wrote:

I'm trying to develop a CGI app in harbour. One of it's feature is to allow user to upload a document. How do I handle this in CGI Harbour? I found this topic in perl but don't know how to translate this in Harbour. Please help. http://www.sitepoint.com/uploading-files-cgi-perl/

TipCgi doesn't manage file upload as it is.

If you write the file_upload.html as in your link and an Harbour upload cgi like:

function main()

   local oCgi := TipCgi():new()

   oCgi:Header( "Content-Type: text/html" )

   oCgi:write( "<html><head><title>Upload</title></head><body>" )

   oCgi:write( hb_valtoexp( oCgi:HTTP_RAW_POST_DATA ) )

   oCgi:write( "</body></html>" )

   return oCgi:flush()

built using:

hbmk2 upload.prg -oupload.cgi hbtip.hbc -gtcgi

you'll see what the cgi script get in input.

Then you can parse the oCgi:HTTP_RAW_POST_DATA var following the info as in http://www.w3.org/TR/html4/interact/forms.html#file-select.

best regards,
Lorenzo Fiorini


Daniele Campagna

unread,
Feb 1, 2014, 6:52:29 PM2/1/14
to harbou...@googlegroups.com
--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users
 
---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 OK I have a working app, no use of any lib, just HB raw code.
I jump in, after a while, and offer my help if the OP has not yet solved.
Dan

clipper6

unread,
Feb 2, 2014, 8:18:09 PM2/2/14
to harbou...@googlegroups.com
Please excuse my ignorance. With regard to your code below how do I save the uploaded file (specify filename & path)? Newbie to web and CGI.

clipper6

unread,
Feb 2, 2014, 8:20:21 PM2/2/14
to harbou...@googlegroups.com, DaNiEl MaXiMiLiAnO
Is there a compiled version of the library for MS Windows?

clipper6

unread,
Feb 2, 2014, 9:50:05 PM2/2/14
to harbou...@googlegroups.com
Do you have any example on how to use the class below. Thanks.

Lorenzo Fiorini

unread,
Feb 3, 2014, 4:18:51 AM2/3/14
to harbou...@googlegroups.com
On Mon, Feb 3, 2014 at 3:50 AM, clipper6 <arl...@gmail.com> wrote:
 
Do you have any example on how to use the class below. Thanks.

I've developed an entire CRM using TipCGI. The base code is:


function main()

   local oCgi := TipCgi():new()

   oCgi:Header( "Content-Type: text/html" )

   oCgi:write( "<html><head><title>My first CGI</
title></head><body>" )

   // GET parameters are in oCgi:hGets and POST ones are in oCgi:hPosts

   // Sessions are managed using oCgi:StartSession() and oCgi:DestroySession()

   oCgi:write( "Hello World!" )


   oCgi:write( "</body></html>" )

   return oCgi:flush()

then you call that executable from your html/js. That's all.
The hard part is html/js/css, server configuration, perfomance etc.

best regards,
Lorenzo Fiorini





clipper6

unread,
Feb 3, 2014, 7:47:29 PM2/3/14
to harbou...@googlegroups.com
Thanks a lot LF!
Message has been deleted

clipper6

unread,
Feb 3, 2014, 8:15:17 PM2/3/14
to harbou...@googlegroups.com
Below is an example of session in PHP:

<?php
session_start();
// store session data
$_SESSION['views']=1;
?>
<html>
<body>
<?php
//retrieve session data
echo "Pageviews=". $_SESSION['views'];
?>
</body>
</html>

Is TIPCgi similar to this. Is there an example that shows how it is done? I hope everyone would be patient with me. I'm just  tasked by our company to develop a web app but I am newbie to web technology.




On Monday, February 3, 2014 5:18:51 PM UTC+8, LF wrote:

clipper6

unread,
Feb 3, 2014, 8:37:35 PM2/3/14
to harbou...@googlegroups.com
I will answer my own question. I did something like this:


function main()

   local oCgi := TipCgi():new()
   oCgi:StartSession()
   oCgi:hSession['request'] := "login"

  
   oCgi:Header( "Content-Type: text/html" )

   oCgi:write( "<html><head><title>My first CGI</title></head><body>" )


   // GET parameters are in oCgi:hGets and POST ones are in oCgi:hPosts
   // Sessions are managed using oCgi:StartSession() and oCgi:DestroySession()

   oCgi:write( oCgi:cSID + "<br>")
   oCgi:write( oCgi:cSessionSavePath + "<br>" )
   oCgi:write( oCgi:hSession['request'] + "<br>" )

   oCgi:write( "Hello World!"  + "<br>")


   oCgi:write( "</body></html>" )

   return oCgi:flush()

Lorenzo Fiorini

unread,
Feb 4, 2014, 9:33:58 AM2/4/14
to harbou...@googlegroups.com
On Tue, Feb 4, 2014 at 2:37 AM, clipper6 <arlie.c@gmail.com> wrote:
 
I will answer my own question. I did something like this:

Ok, you got the basic idea :)

best regards,
Lorenzo

clipper6

unread,
Feb 4, 2014, 8:14:27 PM2/4/14
to harbou...@googlegroups.com
Going back to how to upload a file. I found this html and PHP code:

<html><body>
<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
</body></html>

//upload_file.php
<?php
$allowedExts = array("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 20000)
&& in_array($extension, $allowedExts))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br>";
    echo "Type: " . $_FILES["file"]["type"] . "<br>";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

What is the equivalent "move_uploaded_file()" function in HB? I'm really stuck in this upload functionality. How do I get the file handle so I can save the uploaded to file? Please help.



On Saturday, February 1, 2014 1:00:37 AM UTC+8, LF wrote:

Lorenzo Fiorini

unread,
Feb 5, 2014, 4:24:13 AM2/5/14
to harbou...@googlegroups.com
On Wed, Feb 5, 2014 at 2:14 AM, clipper6 <arl...@gmail.com> wrote:
 
Going back to how to upload a file. I found this html and PHP code:
...
What is the equivalent "move_uploaded_file()" function in HB? I'm really stuck in this upload functionality. How do I get the file handle so I can save the uploaded to file? Please help.

TipCGI is not an alternative to PHP o Perl.
It was designed as a very simple way to get basic CGI input/output.
I would consider other options for your first web app.
It lacks tons of functionalities and security controls. I'd never use it in a public accessible server.

If you're so brave to continue with TipCGI :)  below there is a function to decode a form-data post.
It's only an example and I tested it only with the file_upload.html in the example link.

In hForm[ "photo" ][ "filename" ] there is the file name and in
hForm[ "photo" ][ "data" ] there is the raw data so something like:

hb_memowrit( hForm[ "photo" ][ "filename" ], hForm[ "photo" ][ "data" ] )

is the next step.

However never do something like that in a real script.
The 1st, 2nd and 3rd rule of the web development is NEVER TRUST THE INPUT.
You need to define your paths, check the sizes, clean the filename, check the encoding of the data and so on.
There are many resources on the web about this.

best regards,
Lorenzo Fiorini

function main()

   local oCgi := TipCgi():new()
   local hForm

   oCgi:Header( "Content-Type: text/html; charset=windows-1252" )


   oCgi:write( "<html><head><title>Upload</title></head><body>" )

   hForm := getformdata( oCgi )

   oCgi:write( hForm[ "photo" ][ "filename" ] )


   oCgi:write( "</body></html>" )

   return oCgi:flush()

function getformdata( oCgi )

   local aData := hb_atokens( oCgi:HTTP_RAW_POST_DATA, chr(13)+chr(10) )
   local hForm := {=>}
   local cTmp
   local aTmp
   local aRows := {}
   local aField := {}
   local cName
   local cFile

   if !empty( aData )
      for each cTmp in aData
         if left( cTmp, 2 ) == "--"
            if !empty( aField )
               aadd( aRows, aField )
               aField := {}
            endif
         else
            aadd( aField, cTmp )
         endif
      endfor
   endif

   if !empty( aRows )
      for each aField in aRows
         aTmp := hb_atokens( aField[ 1 ], ";" )
         if aTmp[ 1 ] == "Content-Disposition: form-data"
            cName := strtran( hb_atokens( aTmp[ 2 ], "=" )[ 2 ], '"', '' )
            if len( aTmp ) > 2
               cFile := strtran( hb_atokens( aTmp[ 3 ], "=" )[ 2 ], '"', '' )
               hForm[ cName ] := { "type" => "file", "filename" => cFile, "mime" => alltrim( hb_atokens( aField[ 2 ], ":" )[ 2 ] ), "data" => aField[ 4 ] }
            else
               hForm[ cName ] := { "type" => "field", "data" => aField[ 3 ] }
            endif
         endif
      endfor
   endif

   return hForm




marek.h...@interia.pl

unread,
Feb 5, 2014, 10:48:38 AM2/5/14
to harbou...@googlegroups.com
*----

Hi,

IMHO cgi is not a good idea to load large files.

On this group, I wrote once about cooperate harbour and blue imp ( lib in java script) in/when loading large files. Link to blue imp :

https://github.com/blueimp/jQuery-File-Upload/

The harbor http server well adapted to this javascrip lib, so as not to accept all of the memory, only the file sequentially to descend like a frame comming.


Regards,
Marek Horodyski


clipper6

unread,
Feb 5, 2014, 9:53:20 PM2/5/14
to harbou...@googlegroups.com
Only small PDF files will be uploaded and downloaded.

clipper6

unread,
Feb 5, 2014, 9:56:03 PM2/5/14
to harbou...@googlegroups.com
My issue is how Harbour/Clipper will get the file handle so I can write it to file.


On Wednesday, February 5, 2014 11:48:38 PM UTC+8, homar wrote:

clipper6

unread,
Jun 29, 2014, 9:58:19 PM6/29/14
to harbou...@googlegroups.com
Based on your code below. How do I set the path where to save the PDF file?

LF    
Feb 24
Re: [harbour-users] Re: CGI Form POST Issue

On Mon, Feb 24, 2014 at 8:16 AM, clipper6 <arl...@gmail.com> wrote:

    If you don't mind, can you post your test form and HB code here for my reference. Thanks.

file_upload.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>File Upload</title>
</head>
<body>
<form action="/cgi-bin/upload.cgi" method="post"
enctype="multipart/form-data">
<p>Photo to Upload: <input type="file" name="photo" /></p>

<p>Your Email Address: <input type="text" name="email_address" /></p>
<p><input type="submit" name="Submit" value="Submit Form" /></p>
</form>
</body>
</html>

upload.prg:

Lorenzo Fiorini

unread,
Jun 30, 2014, 4:41:00 PM6/30/14
to harbou...@googlegroups.com
On Mon, Jun 30, 2014 at 3:58 AM, clipper6 <arl...@gmail.com> wrote:
 
Based on your code below. How do I set the path where to save the PDF file?

You have the filename and the data so basically it's a hb_memowrit( newfilename( hForm[ "photo" ][ "filename"] ), hForm[ "photo" ][ "data" ] )
where newfilename is a function that parse the filename, remove the path part and keep filename and extension
( in this case you have to decide what to do in case of name collision ( two users that upload different files with same name ) or
you can create a completely new file names based on system data like username+date+time.

best regards,
Lorenzo

clipper6

unread,
Jul 22, 2014, 9:41:25 PM7/22/14
to harbou...@googlegroups.com
For jpg file type this works hForm[ "photo" ][ "filename" ] but for png I get an error. How about PDF file how do I determine the file type? hForm[ "mime" ][ "filename" ]?
Reply all
Reply to author
Forward
0 new messages