Page 1 of 1

Harbour for the web

Posted: Sat Aug 11, 2018 6:18 am
by Antonio Linares
Up to now, when we talked about Harbour and FiveWeb we used them as a way to develop cgi-bin apps that could only be executed from the public_html/cgi-bin folder.

From now on, and using this simple trick, we can execute Harbour and FiveWeb from the web from any folder, not just the cgi-bin one :-)

Simply place this index.php file in the folder where you want to execute Harbour (yes, I mean the Harbour compiler itself!) or a FiveWeb app:

index.php

Code: Select all

<?php
   exec( "./harbour", $output );

   foreach( $output as $x => $value )
   {
     printf( "%s<br>", $value );
   }
?>
Here you have an example: (notice this is not the cgi-bin folder!)
http://www.fivetechsoft.com/erp

Re: Harbour for the web

Posted: Sat Aug 11, 2018 5:42 pm
by cdmmaui
Hi Antonio,

This is what I get when I click URL: http://www.fivetechsoft.com/erp

Image

Re: Harbour for the web

Posted: Sun Aug 12, 2018 6:00 am
by Antonio Linares
Darrell,

It is a proof of concept. The point is that we can execute a Harbour app from a web page in the remote server
and it does not have to be placed at the cgi-bin directory.

You can build a Harbour app that opens DBFs or a SQL database, does whatever processing is required and return
a result as HTML (FiveWeb uses "bootstrap" to ease the HTML generation).

This opens endless possibilities. There is no need at all for xbase++, and you can keep using your Harbour apps ;-)

Re: Harbour for the web

Posted: Sun Aug 12, 2018 7:00 am
by Otto
Dear Antonio,
This sounds great. Can you please post a little sample.
Do you mean we can run a Harbour exe from a html .

Best regards
Otto

Re: Harbour for the web

Posted: Sun Aug 12, 2018 12:05 pm
by cdmmaui
Dear Antonio,

Noted, however, all of the web applications that I created have never run from CGI-BIN, I have been able to configure IIS to run from whatever folder I want. I set virtual folder in IIS then updated ISAPI/CGI restrictions for each DLL which then calls the EXE and then set the Windows OS permissions for NETWORK SERVICE and IIS Users.

Here is the source code and output:
#include "adsdbe.ch"
#include "ads.ch"
#include "\CLIPWEB\INCLUDE\CLIPWEB.H"
#include "cdm.h"

FUNCTION MAIN( cIniFile )
_TrackUpdate( cIniFile )
RETURN Void

FUNCTION _TrackUpdate( cIniFile )


LOCAL oSession , ;
nCnt := 0 , ;
lPass := .F. , ;
cUID := '' , ;
cPID := '' , ;
cName := '' , ;
aEvent := {} , ;
aStates := {} , ;
aUncode := {} , ;
aHour := {} , ;
aMinutes := {} , ;
aSupplier := {} , ;
aConsignee := {} , ;
aForwarder := {} , ;
aIso := {} , ;
cGpsLink := ""

// Init...
CgiInit()

IF cIniFile != Nil
nHOut :=cgiForm(cIniFile)
else
RETURN Void
ENDIF

// Init...
SET EPOCH TO 1980
SET DATE FORMAT TO "MM/DD/YYYY"
SET EXCLUSIVE OFF
SET DELETED ON
SET DECIMALS TO 2

// Init...
cUID := _CgiGet( 'userid' )
cPID := _CgiGet( 'password' )
cUTYPE := "OPERATIONS"
cCID := ""
cAID := ""
cLogo := ""
cWid := "100"
cHgt := "100"
cComp := ""
lLink := .F.
cLastD := ""
cLastT := ""
nRowMax := nMax
nRowCnt := 0
cUID := _ParamRead( cQueryString, "LINK=", @lLink )
nRecId := VAL( _ParamRead( cQueryString, "ID=" ) )
cMode := "O"
cFileno := ""
cPono := ""
cVendid := ""
cVendname := ""
cVendref := ""
cConsid := ""
cConsname := ""
cConsref := ""
cOforwid := ""
cOforwname := ""
cDforwid := ""
cDforwname := ""
cCarrier := ""
cBookno := ""
cMbl := ""
cHbl := ""
cSeaams := ""
cVessel := ""
cVoyage := ""
cPickdate := ""
cReceipt := ""
cPol := ""
cEtd := ""
cPoul := ""
cEta := ""
cDelivery := ""
cEtaDelv := ""
cCtnrno := ""
cSealno := ""
cQty := ""
cKgs := ""
cCbm := ""
cCommodity := ""
cModule := ""
cLogname := ""
cCompid := ""
cIsfdata := ""
cIsfdate := ""
cAmsdata := ""
cAmsdate := ""
cAesdata := ""
cAesdate := ""
cProfile := ""
aCtnrno := {}

// Default...
_HtmlLoad()

SET DEFAULT TO ( cRoot )

// connect to the ADS server
IF lAds
oSession := dacSession():New( "ADSDBE", cRoot )

// check if we are connected to the ADS server
IF ( ! oSession:isConnected( ) )
_AdsErr( LTRIM( STR( oSession:getLastError(), 9 ) ) )
RETURN Void
ENDIF

// use FPT/CDX compatible files
DbeInfo( COMPONENT_DATA, ADSDBE_TBL_MODE , ADSDBE_CDX)
DbeInfo( COMPONENT_ORDER, ADSDBE_INDEX_EXT, "CDX")
ENDIF

// Load Profile...
IF ! _LoadProfile()
_AdsOpenErr( cRoot, 'intmgr', oSession )
RETURN Void
ENDIF

// User...
lPass := _UserDetails( lLink, cUID, cPID, @cName, @cUTYPE, @cCID, @cAID, @cLastD, @cLastT, @cLogname, .T. )
IF ! lPass
_LoginError( cUID + IF( lLink, "--LINK=YES", "--LINK=NO"), oSession )
RETURN Void
ENDIF
cUserDet := _GetUser( cUid )
cCustid := _GetUserCustomerId( cUid )

// Open...
_db( cWinFrtData, 'uncode' )
_db( cRoot, 'edi' )
_db( cRoot, 'edi315' )
_db( cRoot, 'rcactnr' )
_db( cRoot, 'rca' )
IF nRecId>0
GO nRecId
cMode := ALLTRIM( rca->mode )
cFileno := ALLTRIM( rca->file )
cShipname := ALLTRIM( rca->shipname )
cShipref := ALLTRIM( rca->ref )
cConsname := ALLTRIM( rca->consname )
cConsref := ALLTRIM( rca->consref )
cProfile := ALLTRIM( rca->profile )
cCarrier := ALLTRIM( rca->carrier )
cBookno := ALLTRIM( rca->booking )
cMbl := ALLTRIM( rca->master )
cHbl := ALLTRIM( rca->house )
cVessel := ALLTRIM( rca->vessel )
cVoyage := ALLTRIM( rca->flight1 )
cReceipt := ALLTRIM( rca->origin )
cPol := ALLTRIM( rca->pol )
cEtd := DTOC( rca->export )
cPoul := ALLTRIM( rca->poul )
cEta := DTOC( rca->import )
cDelivery := ALLTRIM( rca->plc_delv )
cEtaDelv := DTOC( rca->eta_poe )
cQty := ALLTRIM( rca->pcs )
cKgs := LTRIM( STR( rca->kgs, 12, 2 ) )
cCbm := LTRIM( STR( rca->cm , 12, 3 ) )
cCommodity := ALLTRIM( rca->comm )

SELECT rcactnr
GO TOP
SEEK rca->serial
IF FOUND()
DO WHILE ! EOF() .AND. ( rcactnr->serial==rca->serial )
IF ! EMPTY( rcactnr->ctnr )
AADD( aCtnrno, rcactnr->ctnr )
ENDIF
SELECT rcactnr
SKIP
ENDDO
ENDIF
ENDIF

put( [<div id="wrapper">] )
put( [ <div id="head">] )
put( [ <div id="logo_user_details">] )
put( [ <h1 id="logo"><a href="#"><img src="images/logo.jpg" alt=""></a></h1>] )
put( [ <div id="user_details">] )
put( [ <ul id="user_details_menu">] )
put( [ <li>Welcome <strong>] + cName + [</strong></li>] )
put( [ <li class="user_details_menu_options">] )
put( [ <ul id="user_access">] )
put( [ <li class="first"><a target="_blank" href="#">User Guide</a></li>] )
put( [ <li class="user_access_line">|</li>] )
put( [ <li class="last"><a href="] + cLogout + [">Log out</a></li>] )
put( [ </ul>] )
put( [ </li>] )
put( [ </ul>] )
put( [ </div>] )
put( [ </div>] )
put( [ </div>] )
put( [ <div id="content">] )
put( [ <div id="page">] )
put( [ <div class="inner">] )
put( [ <div class="section table_section">] )
put( [ <div class="title_wrapper">] )
put( [ <h2>] + cClientName + [</h2>] )
put( [ </div>] )
put( [ <div class="section_content">] )
put( [ <div class="section_content_padding">] )
put( [ <div class="dashboard_menu_wrapper">] )
put( [ <ul class="dashboard_menu">] )
put( [ <li><a class="back" href="shiplist.dll?LINK=] + cUid + ["><span>Back</span></a></li>] )
put( [ <li><a class="d7" href="dashboard.dll?LINK=] + cUid + ["><span>Dashboard</span></a></li>] )
put( [ </ul>] )
put( [ </div>] )
put( [ </div>] )
put( [ </div>] )
put( [ </div>] )
put( [ <form action="shiplist.dll?LINK=] + cUid + [" method="POST">] )
put( [ <div class="section table_section">] )
put( [ <div class="title_wrapper">] )
put( [ <h2>Shipment Information</h2>] )
put( [ </div>] )

put( [ <div class="section_content">] )
put( [ <div class="table_wrapper">] )
put( [ <div class="table_wrapper_inner" style="padding:0;">] )
put( [ <table>] )

put( [ <tr>] )
put( [ <th>Shipment No.</th>] )
put( [ <th><input name="fileno" type="text" size="30" value="] + cFileno + ["></th>] )
put( [ <th>HBL No.</th>] )
put( [ <th><input name="hbl" type="text" size="30" value="] + cHbl + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th colspan=4>&nbsp;</th>] )
put( [ </tr>] )

put( [ </table>] )

put( [ </div>] )
put( [ </div>] )
put( [ </div>] )

put( [ <div class="title_wrapper">] )
put( [ <h2>Shipment Parties</h2>] )
put( [ </div>] )

put( [ <div class="section_content">] )
put( [ <div class="table_wrapper">] )
put( [ <div class="table_wrapper_inner" style="padding:0;">] )
put( [ <table>] )

put( [ <tr>] )
put( [ <th>Shipper</th>] )
put( [ <th><input name="shipname" type="text" size="50" value="] + cShipname + ["></th>] )
put( [ <th>Shipper's Reference</th>] )
put( [ <th><input name="shipref" type="text" size="30" value="] + cShipref + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Consignee</th>] )
put( [ <th><input name="consname" type="text" size="50" value="] + cConsname + ["></th>] )
put( [ <th>Consignee's Reference</th>] )
put( [ <th><input name="consref" type="text" size="30" value="] + cConsref + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Profile</th>] )
put( [ <th colspan=3><input name="profile" type="text" size="50" value="] + cProfile + ["></th>] )
put( [ </tr>] )


put( [ <tr>] )
put( [ <th colspan=4>&nbsp;</th>] )
put( [ </tr>] )

put( [ </table>] )

put( [ </div>] )
put( [ </div>] )
put( [ </div>] )


put( [ <div class="title_wrapper">] )
put( [ <h2>Shipment Routing Details</h2>] )
put( [ </div>] )

put( [ <div class="section_content">] )
put( [ <div class="table_wrapper">] )
put( [ <div class="table_wrapper_inner" style="padding:0;">] )
put( [ <table>] )

put( [ <tr>] )
put( [ <th>Carrier</th>] )
put( [ <th colspan=3><input name="carrier" type="text" size="04" value="] + cCarrier + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Conveyance</th>] )
put( [ <th colspan=3><input name="vessel" type="text" size="45" value="] + cVessel + ["></th>] )
//put( [ <th>Voyage/Flight</th>] )
//put( [ <th><input name="voyage" id="voyage" type="text" size="10" value="] + cVoyage + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Place of Receipt</th>] )
put( [ <th><input name="receipt" type="text" size="45" value="] + cReceipt + ["></th>] )
put( [ <th>Loaded at Place of Receipt</th>] )
put( [ <th><input id="pickdate" name="pickdate" type="text" size="10" value="] + cPickdate + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Port of Loading</th>] )
put( [ <th><input id="pol" name="pol" type="text" size="40" value="] + cPol + ["></th>] )
put( [ <th>E.T.D.</th>] )
put( [ <th><input id="etd" name="etd" type="text" size="10" value="] + cEtd + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Port of Discharge</th>] )
put( [ <th><input id="poul" name="pol" type="text" size="40" value="] + cPoul + ["></th>] )
put( [ <th>E.T.A.</th>] )
put( [ <th><input id="eta" name="eta" type="text" size="10" value="] + cEta + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Place of Delivery</th>] )
put( [ <th><input name="delivery" type="text" size="45" value="] + cDelivery + ["></th>] )
put( [ <th>E.T.A. Final Destination</th>] )
put( [ <th><input id="etadelv" name="etadelv" type="text" size="10" value="] + cEtadelv + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th colspan=4>&nbsp;</th>] )
put( [ </tr>] )

put( [ </table>] )

put( [ </div>] )
put( [ </div>] )
put( [ </div>] )


put( [ <div class="title_wrapper">] )
put( [ <h2>Shipment Compliance</h2>] )
put( [ </div>] )

put( [ <div class="section_content">] )
put( [ <div class="table_wrapper">] )
put( [ <div class="table_wrapper_inner" style="padding:0;">] )
put( [ <table>] )

put( [ <tr>] )
put( [ <th>ISF (10+2)</th>] )
put( [ <th><input name="isfdata" type="text" size="75" value="] + cIsfdata + ["></th>] )
put( [ <th>On File</th>] )
put( [ <th><input name="isfdate" type="text" size="10" value="] + cIsfdate + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>Sea AMS (24 Hr Rule)</th>] )
put( [ <th><input name="amsdata" type="text" size="75" value="] + cAmsdata + ["></th>] )
put( [ <th>On File</th>] )
put( [ <th><input name="amsdate" type="text" size="10" value="] + cAmsdate + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>ACE AES</th>] )
put( [ <th><input name="aesdata" type="text" size="75" value="] + cAesdata + ["></th>] )
put( [ <th>On File</th>] )
put( [ <th><input name="aesdate" type="text" size="10" value="] + cAesdate + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th colspan=4>&nbsp;</th>] )
put( [ </tr>] )


put( [ </table>] )

put( [ </div>] )
put( [ </div>] )
put( [ </div>] )

put( [ <div class="title_wrapper">] )
put( [ <h2>Shipment Commodity Details</h2>] )
put( [ </div>] )

put( [ <div class="section_content">] )
put( [ <div class="table_wrapper">] )
put( [ <div class="table_wrapper_inner" style="padding:0;">] )
put( [ <table>] )

put( [ <tr>] )
put( [ <th>Commodity</th>] )
put( [ <th><input name="commodity" type="text" size="50" value="] + cCommodity + ["></th>] )
put( [ <th>Quantity</th>] )
put( [ <th><input name="qty" type="text" size="30" value="] + cQty + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th>KGS</th>] )
put( [ <th><input name="kgs" type="text" size="10" value="] + cKgs + ["></th>] )
put( [ <th>CBM</th>] )
put( [ <th><input name="cbm" type="text" size="10" value="] + cCbm + ["></th>] )
put( [ </tr>] )

put( [ <tr>] )
put( [ <th colspan=4>&nbsp;</th>] )
put( [ </tr>] )

put( [ </table>] )

put( [ </div>] )
put( [ </div>] )
put( [ </div>] )

put( [ <div class="title_wrapper">] )
put( [ <h2>Shipment Tracking</h2>] )
put( [ </div>] )

put( [ <div class="section_content">] )
put( [ <div class="table_wrapper">] )
put( [ <div class="table_wrapper_inner" style="padding:0;">] )
put( [ <table>] )

put( [ <tr>] )
put( [ <th>Container No.</th>] )
put( [ <th>Event</th>] )
put( [ <th>Location</th>] )
put( [ <th>Event Date</th>] )
put( [ </tr>] )

FOR nX1=1 TO LEN(aCtnrno)
cCtnrno := aCtnrno[nX1]
aEvent := {}

SELECT edi315
SET ORDER TO TAG S2
GO TOP
SEEK LEFT( ALLTRIM(cCtnrno) + SPACE(11), 11 )
IF FOUND()
DO WHILE ! EOF() .AND. ( ALLTRIM(edi315->ctnr)==ALLTRIM(cCtnrno) )

IF (! (ALLTRIM(edi315->bm)==ALLTRIM(cBookno))) .AND. (! (ALLTRIM(edi315->bn)==ALLTRIM(cBookno)))
SKIP
LOOP
ENDIF

cC1 := ALLTRIM( edi315->b4 )+DTOS(edi315->b4d)+LEFT(edi315->b4t,5)
lC1 := .T.
FOR nX2=1 TO LEN(aEvent)
IF cC1==aEvent[nX2]
lC1 := .F.
EXIT
ENDIF
NEXT NX2
IF ! lC1
SKIP
LOOP
ENDIF
AADD( aEvent, cC1 )

cGpsLink := ""
cLatitude := ALLTRIM(edi315->latitude)
cLongitude := ALLTRIM(edi315->longitude)

IF (! EMPTY(cLatitude)) .AND. (! EMPTY(cLongitude))
cGpsLink := "http://maps.google.com/?t=k&z=500&q=" + cLatitude + "," + cLongitude
ENDIF

put( [<tr>] )

// Data...
cDat := ALLTRIM( UPPER( edi315->ctnr ) )
cDLink := cDat
IF EMPTY( cDat )
cDat := "&nbsp;"
ENDIF
put( [<td>] + cDat + [</td>] )

cDat := _EventDescription( edi315->b4 )
IF EMPTY( cDat )
cDat := "&nbsp;"
ENDIF
put( [<td>] + cDat + [</td>] )

cDat := ALLTRIM( UPPER( edi315->r4e ) )
IF EMPTY( cDat ) .AND. (! EMPTY(edi315->r4c2))
cDat := LEFT(edi315->r4c2,5)
ENDIF
IF LEN(cDat)=5
SELECT uncode
SET ORDER TO TAG S1
GO TOP
SEEK cDat
IF FOUND()
cDat := LEFT( ALLTRIM( uncode->expand ), 30 )
IF EMPTY(uncode->isoname)
IF ! EMPTY( uncode->iso )
cDat += ", " + ALLTRIM( uncode->iso )
ENDIF
ELSE
cDat += ", " + ALLTRIM( uncode->isoname )
ENDIF
ENDIF
ENDIF
IF ! EMPTY( cGpslink )
cDat += [<a class="action_gps" target="_blank" href="] + cGpsLink + [" data-toggle="tooltip" title="Satellite Tracking">&nbsp;</a>&nbsp;]
ENDIF
IF EMPTY( cDat )
cDat := "&nbsp;"
ENDIF
put( [<td>] + cDat + [</td>] )

cDat := DTOC(edi315->b4d) + ' @ ' + LEFT(edi315->b4t,5)
IF EMPTY( cDat )
cDat := "&nbsp;"
ENDIF
put( [<td>] + cDat + [</td>] )

put( [</tr>] )

SELECT edi315
SKIP
ENDDO
ELSE
put( [<tr>] )
cDat := cCtnrno
put( [<td>] + cDat + [</td>] )
cDat := 'Waiting for Carrier Tracking Details . . .'
put( [<td colspan=3>] + cDat + [</td>] )
put( [</tr>] )
ENDIF
NEXT nX1
put( [ <tr>] )
put( [ <th colspan=4>&nbsp;</th>] )
put( [ </tr>] )

put( [ </table>] )

put( [ </div>] )
put( [ </div>] )
put( [ </div>] )


put( [ <div class="title_wrapper">] )
put( [ <h2>Available Shipment Documents</h2>] )
put( [ </div>] )

put( [ <div class="section_content">] )
put( [ <div class="table_wrapper">] )
put( [ <div class="table_wrapper_inner" style="padding:0;">] )
put( [ <table>] )

put( [ <tr>] )
put( [ <th colspan=4>&nbsp;</th>] )
put( [ </tr>] )

put( [ </table>] )

put( [ </div>] )
put( [ </div>] )
put( [ </div>] )




put( '<input type=hidden name="USERID" value="' + cUID + '">' )
put( '<input type=hidden name="RECID" value="' + LTRIM(STR(nRecId,9)) + '">' )

put( [ </div>] )

put( '<input type="submit" name="A1" value="R E T U R N * T O * S H I P M E N T * L I S T" style="border:1 solid #CDCDCD; font-family: tahoma,Verdana; height: 29; position: relative; color:#111111; padding-left:4px; padding-right:4px; padding-top:4; padding-bottom:4; background-color:#DCDCDC">' )

put( [<script src="https://ajax.googleapis.com/ajax/libs/j ... /jquery.js" type="text/javascript"></script>] )
put( [<script src="js/chosen.jquery.js" type="text/javascript"></script>] )
put( [<script src="js/prism.js" type="text/javascript" charset="utf-8"></script>] )
put( [<script src="js/init.js" type="text/javascript" charset="utf-8"></script> ] )


put( [ </form>] )
put( [ </div>] )
put( [ </div>] )
put( [ </div>] )
put( [</div>] )

// Footer...
_CdmFooter()

put( [</body>] )
put( [</html>] )

IF lAds
oSession:disconnect()
ENDIF
DbCloseAll()
CloseCGISession()

RETURN Void

Image

Re: Harbour for the web

Posted: Sun Aug 12, 2018 12:40 pm
by Antonio Linares
Dear Otto,
Otto wrote:Dear Antonio,
This sounds great. Can you please post a little sample.
Do you mean we can run a Harbour exe from a html .

Best regards
Otto
If you provide me (on a private email) access to your bluehost server I will set a complete working example for you :-)

Yes, we can run Harbour apps from our web servers and there is no need to learn php, etc ;-)

Re: Harbour for the web

Posted: Sun Aug 12, 2018 12:43 pm
by Antonio Linares
Darrell,

Yes, right.

The point is that Linux servers are much cheaper and common than Windows ones, and we can easily run Harbour apps from them :-)

FiveTech uses Bluehost http://www.bluehost.com in USA and the Harbour apps are running great from there (linux servers)

Re: Harbour for the web

Posted: Sat Aug 18, 2018 12:07 pm
by Otto
Dear Antonio thank you. I send you an email. Best regards Otto

Re: Harbour for the web

Posted: Wed Aug 29, 2018 7:21 am
by Romeo
Hi Otto,

did you get from Antonio the example for Web App with harbour ?

Do you like it ?

Can you give me a link to the sample web app ?

tks

Romeo

Re: Harbour for the web

Posted: Wed Aug 29, 2018 7:43 am
by Antonio Linares
Romeo,

Otto provided me access for a Windows server.

I was expecting a Linux dedicated server.

I am looking now for a cheap Linux dedicated server to hire :-)

Once I found it I will post the examples there and here the urls for everyone to review them ;-)

Re: Harbour for the web

Posted: Wed Aug 29, 2018 9:34 am
by lucasdebeltran

Re: Harbour for the web

Posted: Wed Aug 29, 2018 2:42 pm
by Antonio Linares
We have already hired a dedicated server at Amazon ;-)

Re: Harbour for the web

Posted: Sun Sep 09, 2018 7:39 pm
by Marcelo Roggeri
Hola Antonio estoy atento a los ejemplos que puedas subir al servidor.
Saludos
Marcelo