* examples/uhttpd2/uwidgets.prg
* examples/uhttpd2/uhbext.prg
* examples/uhttpd2/app.prg
+ examples/uhttpd2/umutex.c
* Embedded C moved to separate file.
% Using Harbour's hb_HGetDef() instead of local version.
412 lines
13 KiB
Plaintext
412 lines
13 KiB
Plaintext
/*
|
|
* $Id$
|
|
*/
|
|
|
|
#include "hbclass.ch"
|
|
#include "common.ch"
|
|
#include "fileio.ch"
|
|
|
|
#define CR_LF (CHR(13)+CHR(10))
|
|
|
|
REQUEST DBFCDX
|
|
|
|
MEMVAR server, get, post, cookie, session
|
|
|
|
STATIC s_aMap
|
|
|
|
FIELD USER, NAME, PASSWORD, CODE, PRICE, TOTAL, TITLE
|
|
|
|
FUNC main()
|
|
LOCAL oServer
|
|
|
|
IF HB_ARGCHECK("help")
|
|
? "Usage: app [options]"
|
|
? "Options:"
|
|
? " //help Print help"
|
|
? " //stop Stop running server"
|
|
RETURN 0
|
|
ENDIF
|
|
|
|
IF HB_ARGCHECK("stop")
|
|
HB_MEMOWRIT(".uhttpd.stop", "")
|
|
RETURN 0
|
|
ELSE
|
|
FERASE(".uhttpd.stop")
|
|
ENDIF
|
|
|
|
RDDSETDEFAULT("DBFCDX")
|
|
SET(_SET_DATEFORMAT, "yyyy-mm-dd")
|
|
|
|
IF ! HB_FILEEXISTS("users.dbf")
|
|
FERASE("users.cdx")
|
|
DBCREATE("users", {{"USER", "C", 16, 0}, {"PASSWORD", "C", 16, 0}, {"NAME", "C", 50, 0}},, .T., "user")
|
|
OrdCreate("users", "user", "USER")
|
|
DBCLOSEAREA()
|
|
ELSEIF ! HB_FILEEXISTS("users.cdx")
|
|
DBUSEAREA(.T.,, "users",, .F., .F.)
|
|
OrdCreate("users", "user", "USER")
|
|
DBCLOSEAREA()
|
|
ENDIF
|
|
|
|
IF ! HB_FILEEXISTS("carts.dbf")
|
|
FERASE("carts.cdx")
|
|
DBCREATE("carts", {{"USER", "C", 16, 0}, {"CODE", "C", 16, 0}, {"AMOUNT", "N", 6, 0}, {"TOTAL", "N", 9, 2}},, .T., "cart")
|
|
OrdCreate("carts", "user", "USER+CODE")
|
|
DBCLOSEAREA()
|
|
ELSEIF ! HB_FILEEXISTS("carts.cdx")
|
|
DBUSEAREA(.T.,, "carts",, .F., .F.)
|
|
OrdCreate("carts", "user", "USER+CODE")
|
|
DBCLOSEAREA()
|
|
ENDIF
|
|
|
|
IF ! HB_FILEEXISTS("items.dbf")
|
|
FERASE("items.cdx")
|
|
DBCREATE("items", {{"CODE", "C", 16, 0}, {"TITLE", "C", 80, 0}, {"PRICE", "N", 9, 2}},, .T., "items")
|
|
OrdCreate("items", "code", "CODE")
|
|
DBCLOSEAREA()
|
|
ELSEIF ! HB_FILEEXISTS("item.cdx")
|
|
DBUSEAREA(.T.,, "items",, .F., .F.)
|
|
OrdCreate("items", "code", "CODE")
|
|
DBCLOSEAREA()
|
|
ENDIF
|
|
|
|
oServer := UHttpdNew()
|
|
|
|
oServer:nPort := 8002
|
|
oServer:bIdle := {|o| IIF(HB_FILEEXISTS(".uhttpd.stop"), (FERASE(".uhttpd.stop"), o:Stop()), NIL)}
|
|
|
|
|
|
s_aMap := {"login" => @proc_login(), ;
|
|
"logout" => @proc_logout(), ;
|
|
"register" => @proc_register(), ;
|
|
"account" => @proc_account(), ;
|
|
"account/edit" => @proc_account_edit(), ;
|
|
"main" => @proc_main(), ;
|
|
"shopping" => @proc_shopping(), ;
|
|
"cart" => @proc_cart()}
|
|
|
|
oServer:aMount := ;
|
|
{"/hello" => {{|| UWrite("Hello!")}, .F.}, ;
|
|
"/info" => {{|| UProcInfo()}, .F.}, ;
|
|
"/files/*"=> {{|x| UProcFiles( hb_dirBase() + "files/" + X, .F.)}, .F.}, ;
|
|
"/app/*" => {{|x| UProcWidgets(x, s_aMap)}, .T.}, ;
|
|
"/*" => {{|| URedirect("/app/login")}, .F.}}
|
|
|
|
IF ! oServer:Run()
|
|
? "Server error:", oServer:cError
|
|
RETURN 1
|
|
ENDIF
|
|
|
|
RETURN 0
|
|
|
|
|
|
STATIC FUNC proc_login(cMethod)
|
|
LOCAL cUser, oM, oF, oG
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
oM := UWMainNew()
|
|
oM:Add( UWLabelNew("", "errtxt", "color:red; font-weight:bold;") )
|
|
oM:Add( oF := UWFormNew("") )
|
|
oF:Add( oG := UWLayoutGridNew() )
|
|
oG:Add( UWHtmlNew("User"), 1, 1 )
|
|
oG:Add( UWInputNew("user"), 1, 2 )
|
|
oG:Add( UWHtmlNew("Password"), 2, 1 )
|
|
oG:Add( UWPasswordNew("password"), 2, 2 )
|
|
oG:Add( UWSubmitNew("submit", "Login"), 3, 2 )
|
|
oM:Add( UWHtmlNew(ULink("Register", "register")) )
|
|
ELSEIF cMethod == "POST"
|
|
DBUSEAREA(.T.,, "users", "users", .T., .T.)
|
|
OrdSetFocus("user")
|
|
cUser := PADR(hb_HGetDef(post, "user", ""), 16)
|
|
IF !EMPTY(cUser) .AND. DBSEEK(cUser, .F.) .AND. ! DELETED() .AND. ;
|
|
PADR(hb_HGetDef(post, "password", ""), 16) == FIELD->PASSWORD
|
|
session["loggedin"] := cUser
|
|
URedirect("main")
|
|
ELSE
|
|
URedirect("login?err")
|
|
USessionDestroy()
|
|
ENDIF
|
|
DBCLOSEAREA()
|
|
ELSEIF cMethod == "GET"
|
|
IF HB_HHasKey(get, "err")
|
|
GetWidgetById("errtxt"):cText := "Invalid username or password!"
|
|
ENDIF
|
|
UWDefaultHandler(cMethod)
|
|
USessionDestroy()
|
|
ENDIF
|
|
RETURN .T.
|
|
|
|
|
|
STATIC FUNC proc_register(cMethod)
|
|
LOCAL cUser, cName, cPassword, cPassword2, oM, oF, oG
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
oM := UWMainNew()
|
|
oM:Add( UWLabelNew("", "errtxt", "color:red; font-weight:bold;") )
|
|
oM:Add( oF := UWFormNew("") )
|
|
oF:Add( oG := UWLayoutGridNew() )
|
|
oG:Add( UWHtmlNew("User name"), 1, 1 )
|
|
oG:Add( UWInputNew("user",, "user"), 1, 2 )
|
|
oG:Add( UWHtmlNew("Name"), 2, 1 )
|
|
oG:Add( UWInputNew("name",, "name"), 2, 2 )
|
|
oG:Add( UWHtmlNew("Password"), 3, 1 )
|
|
oG:Add( UWPasswordNew("password"), 3, 2 )
|
|
oG:Add( UWHtmlNew("Password again"), 4, 1 )
|
|
oG:Add( UWPasswordNew("password2"), 4, 2 )
|
|
oG:Add( UWSubmitNew("register", "Register"), 5, 2 )
|
|
ELSEIF cMethod == "POST"
|
|
DBUSEAREA(.T.,, "users", "users", .T., .F.)
|
|
OrdSetFocus("user")
|
|
cUser := hb_HGetDef(post, "user", "")
|
|
cName := hb_HGetDef(post, "name", "")
|
|
cPassword := hb_HGetDef(post, "password", "")
|
|
cPassword2 := hb_HGetDef(post, "password2", "")
|
|
GetWidgetById("user"):cValue := cUser
|
|
GetWidgetById("name"):cValue := cName
|
|
IF EMPTY(cUser) .OR. EMPTY(cName) .OR. EMPTY(cPassword) .OR. EMPTY(cPassword2)
|
|
URedirect("?err=1")
|
|
ELSEIF !(cPassword == cPassword2)
|
|
URedirect("?err=2")
|
|
ELSEIF DBSEEK(cUser, .F.)
|
|
URedirect("?err=3")
|
|
ELSE
|
|
FLOCK()
|
|
DBAPPEND()
|
|
USER := cUser
|
|
NAME := cName
|
|
PASSWORD := cPassword
|
|
DBUNLOCK()
|
|
session["loggedin"] := cUser
|
|
URedirect("main")
|
|
ENDIF
|
|
DBCLOSEAREA()
|
|
ELSEIF cMethod == "GET"
|
|
IF HB_HHasKey(get, "err")
|
|
IF get["err"] == "1"
|
|
GetWidgetById("errtxt"):cText := "All fields are required!"
|
|
ELSEIF get["err"] == "2"
|
|
GetWidgetById("errtxt"):cText := "Passwords does not match!"
|
|
ELSEIF get["err"] == "3"
|
|
GetWidgetById("errtxt"):cText := "This user already exists!"
|
|
ENDIF
|
|
ENDIF
|
|
UWDefaultHandler(cMethod)
|
|
ENDIF
|
|
RETURN .T.
|
|
|
|
|
|
STATIC FUNC proc_account(cMethod)
|
|
LOCAL cUser, cName, oM, oG
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
IF ! HB_HHasKey(session, "loggedin"); URedirect("/app/login"); RETURN .F.
|
|
ENDIF
|
|
DBUSEAREA(.T.,, "users", "users", .T., .F.)
|
|
OrdSetFocus("user")
|
|
ELSEIF cMethod == "GET"
|
|
DBSEEK(session["loggedin"], .F.)
|
|
/* Create object here because user name can be changed in account/edit */
|
|
oM := UWMainNew()
|
|
oM:Add( UWMenuNew():AddItem("Shopping", "shopping"):AddItem("Cart", "cart"):AddItem("Logout", "logout") )
|
|
oM:Add( UWSeparatorNew() )
|
|
oM:Add( oG := UWLayoutGridNew() )
|
|
oG:Add( UWHtmlNew("User name:"), 1, 1 )
|
|
oG:Add( UWHtmlNew(session["loggedin"]), 1, 2 )
|
|
oG:Add( UWHtmlNew("Name:"), 2, 1 )
|
|
oG:Add( UWHtmlNew(NAME), 2, 2 )
|
|
oM:Add( UWHtmlNew(ULink("Edit", "account/edit")) )
|
|
UWDefaultHandler(cMethod)
|
|
ELSEIF cMethod == "EXIT"
|
|
users->(DBCLOSEAREA())
|
|
ENDIF
|
|
RETURN .T.
|
|
|
|
|
|
STATIC FUNC proc_account_edit(cMethod)
|
|
LOCAL cName, cPassword, cPassword2, oM, oG, oF
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
IF ! HB_HHasKey(session, "loggedin"); URedirect("/app/login"); RETURN .F.
|
|
ENDIF
|
|
DBSEEK(session["loggedin"], .F.)
|
|
oM := UWMainNew()
|
|
oM:Add( UWLabelNew("", "errtxt", "color:red; font-weight:bold;") )
|
|
oM:Add( oF := UWFormNew("") )
|
|
oF:Add( oG := UWLayoutGridNew() )
|
|
oG:Add( UWHtmlNew("User name"), 1, 1 )
|
|
oG:Add( UWHtmlNew(session["loggedin"]), 1, 2 )
|
|
oG:Add( UWHtmlNew("Name"), 2, 1 )
|
|
oG:Add( UWInputNew("name", TRIM(NAME), "name"), 2, 2 )
|
|
oG:Add( UWHtmlNew("Password"), 3, 1 )
|
|
oG:Add( UWPasswordNew("password"), 3, 2 )
|
|
oG:Add( UWHtmlNew("Password again"), 4, 1 )
|
|
oG:Add( UWPasswordNew("password2"), 4, 2 )
|
|
oG:Add( UWSubmitNew("save", "Save"), 5, 2 )
|
|
ELSEIF cMethod == "POST"
|
|
DBSEEK(session["loggedin"], .F.)
|
|
cName := hb_HGetDef(post, "name", "")
|
|
cPassword := hb_HGetDef(post, "password", "")
|
|
cPassword2 := hb_HGetDef(post, "password2", "")
|
|
GetWidgetById("name"):cValue := TRIM(cName)
|
|
IF EMPTY(cName)
|
|
URedirect("?err=1")
|
|
ELSEIF (! EMPTY(cPassword) .OR. ! EMPTY(cPassword2)) .AND. ! (cPassword == cPassword2)
|
|
URedirect("?err=2")
|
|
ELSE
|
|
FLOCK()
|
|
NAME := cName
|
|
QOUT("PO DBAPPEND", ALIAS(), RECNO(), cName)
|
|
IF ! EMPTY(cPassword)
|
|
PASSWORD := cPassword
|
|
ENDIF
|
|
DBUNLOCK()
|
|
URedirect("../account")
|
|
ENDIF
|
|
ELSEIF cMethod == "GET"
|
|
IF HB_HHasKey(get, "err")
|
|
IF get["err"] == "1"
|
|
GetWidgetById("errtxt"):cText := "All fields are required!"
|
|
ELSEIF get["err"] == "2"
|
|
GetWidgetById("errtxt"):cText := "Passwords does not match!"
|
|
ENDIF
|
|
ENDIF
|
|
UWDefaultHandler(cMethod)
|
|
ELSEIF cMethod == "EXIT"
|
|
ENDIF
|
|
RETURN .T.
|
|
|
|
|
|
STATIC FUNC proc_main(cMethod)
|
|
LOCAL oM
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
IF ! HB_HHasKey(session, "loggedin"); URedirect("/app/login"); RETURN .F.
|
|
ENDIF
|
|
oM := UWMainNew()
|
|
oM:Add( UWMenuNew():AddItem("Shopping", "shopping");
|
|
:AddItem("Cart", "cart");
|
|
:AddItem("My account", "account");
|
|
:AddItem("Logout", "logout") )
|
|
oM:Add( UWSeparatorNew() )
|
|
oM:Add( UWLabelNew("You can do shopping, or edit your cart using menu links above") )
|
|
ELSEIF cMethod == "GET"
|
|
UWDefaultHandler(cMethod)
|
|
ENDIF
|
|
RETURN .T.
|
|
|
|
|
|
STATIC FUNC proc_shopping(cMethod)
|
|
LOCAL oM, oW, nT, cCode
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
IF ! HB_HHasKey(session, "loggedin"); URedirect("/app/login"); RETURN .F.
|
|
ENDIF
|
|
oM := UWMainNew()
|
|
oM:Add( UWMenuNew():AddItem("Cart", "cart"):AddItem("My account", "account"):AddItem("Logout", "logout") )
|
|
oM:Add( UWSeparatorNew() )
|
|
oM:Add( UWLabelNew("", "cartsum") )
|
|
|
|
DBUSEAREA(.T.,, "carts", "carts", .T., .F.)
|
|
OrdSetFocus("user")
|
|
ORDSCOPE(0, session["loggedin"])
|
|
ORDSCOPE(1, session["loggedin"])
|
|
DBUSEAREA(.T.,, "items", "items", .T., .T.)
|
|
OrdSetFocus("code")
|
|
oW := UWBrowseNew("1")
|
|
oW:AddColumn(101, "Item No.", "CODE")
|
|
oW:AddColumn(102, "Title", "TITLE")
|
|
oW:AddColumn(103, "Price", "PRICE")
|
|
oW:AddColumn(104, "", {|| ULink("Add to cart", "?add=" + TRIM(CODE))}, .T.)
|
|
oM:Add( oW )
|
|
ELSEIF cMethod == "GET"
|
|
IF HB_HHasKey(get, "add")
|
|
cCode := PADR(get["add"], 16)
|
|
IF items->(DBSEEK(cCode)) .AND. carts->(FLOCK())
|
|
IF ! carts->(DBSEEK(session["loggedin"] + cCode))
|
|
carts->(DBAPPEND())
|
|
carts->USER := session["loggedin"]
|
|
carts->CODE := cCode
|
|
ENDIF
|
|
carts->AMOUNT += 1
|
|
carts->TOTAL += items->PRICE
|
|
carts->(DBUNLOCK())
|
|
ENDIF
|
|
URedirect("shopping")
|
|
RETURN .T.
|
|
ENDIF
|
|
nT := 0
|
|
carts->(DBEVAL({|| nT += TOTAL}))
|
|
GetWidgetById("cartsum"):cText := "Your cart is worth: " + LTRIM(STR(nT))
|
|
UWDefaultHandler(cMethod)
|
|
ELSEIF cMethod == "EXIT"
|
|
items->(DBCLOSEAREA())
|
|
carts->(DBCLOSEAREA())
|
|
ENDIF
|
|
RETURN .T.
|
|
|
|
|
|
STATIC FUNC proc_cart(cMethod)
|
|
LOCAL oM, oW, nT, cCode
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
IF ! HB_HHasKey(session, "loggedin"); URedirect("/app/login"); RETURN .F.
|
|
ENDIF
|
|
oM := UWMainNew()
|
|
oM:Add( UWMenuNew():AddItem("Shopping", "shopping"):AddItem("My account", "account"):AddItem("Logout", "logout") )
|
|
oM:Add( UWSeparatorNew() )
|
|
oM:Add( UWLabelNew("", "cartsum") )
|
|
|
|
DBUSEAREA(.T.,, "items", "items", .T., .T.)
|
|
OrdSetFocus("code")
|
|
DBUSEAREA(.T.,, "carts", "carts", .T., .F.)
|
|
OrdSetFocus("user")
|
|
ORDSCOPE(0, session["loggedin"])
|
|
ORDSCOPE(1, session["loggedin"])
|
|
oW := UWBrowseNew("1")
|
|
oW:AddColumn(101, "Item No.", "CODE")
|
|
oW:AddColumn(102, "Title", {|| items->(DBSEEK(carts->CODE, .F.), TITLE)})
|
|
oW:AddColumn(103, "Amount", "AMOUNT")
|
|
oW:AddColumn(104, "Total", "TOTAL")
|
|
oW:AddColumn(104, "", {|| ULink("Delete", "?del=" + TRIM(CODE))}, .T.)
|
|
oM:Add( oW )
|
|
ELSEIF cMethod == "GET"
|
|
IF HB_HHasKey(get, "del")
|
|
cCode := PADR(get["del"], 16)
|
|
IF items->(DBSEEK(cCode)) .AND. carts->(FLOCK())
|
|
IF carts->(DBSEEK(session["loggedin"] + cCode))
|
|
carts->(DBDELETE())
|
|
carts->USER := ""
|
|
carts->CODE := cCode
|
|
ENDIF
|
|
carts->(DBUNLOCK())
|
|
ENDIF
|
|
URedirect("cart")
|
|
RETURN .T.
|
|
ENDIF
|
|
nT := 0
|
|
carts->(DBEVAL({|| nT += TOTAL}))
|
|
GetWidgetById("cartsum"):cText := "Your cart is worth: " + LTRIM(STR(nT))
|
|
UWDefaultHandler(cMethod)
|
|
ELSEIF cMethod == "EXIT"
|
|
items->(DBCLOSEAREA())
|
|
carts->(DBCLOSEAREA())
|
|
ENDIF
|
|
RETURN .T.
|
|
|
|
|
|
STATIC FUNC proc_logout(cMethod)
|
|
LOCAL oM
|
|
? PROCNAME(), cMethod
|
|
IF cMethod == "INIT"
|
|
IF ! HB_HHasKey(session, "loggedin"); URedirect("/app/login"); RETURN .F.
|
|
ENDIF
|
|
oM := UWMainNew()
|
|
oM:Add( UWMenuNew():AddItem("Login", "login") )
|
|
oM:Add( UWSeparatorNew() )
|
|
oM:Add( UWLabelNew("Your session is ended.") )
|
|
ELSEIF cMethod == "GET"
|
|
UWDefaultHandler(cMethod)
|
|
USessionDestroy()
|
|
ENDIF
|
|
RETURN .T.
|