-
Oct 29th, 2021, 05:15 PM
#1
VB6 Web Site/App Server
This project helps you serve web sites/apps with VB6. It is a work in progress. It will eventually become a DLL, but for now it is an EXE project while under development.
It includes a number of nice features to make it easier to deliver websites such as:
- Auto-serves static files (this can be disabled if you want to perform your own file serving).
- Automatically handle If-None-Match headers to return 304 Not Modified when appropriate to save bandwidth.
- Easily handle cookies with the CHttpCookies class.
- Easily handle requests via the CHttpRequest class.
- Easily respond to requests using the CHttpResponse class.
- Include "helper" classes for things like handling dates, encoding HTML entities, "Safe" DB creation, regular expressions, and HTML templates (I call these VBML files, and they have a ".vbml" extension.
- MIME type detection (file extension based).
VBML files are just HTML files with special comments. The app server will detect the comments and raise an event to your app, which can then respond with HTML that will replace the VBML comment. VBML comments are formatted like this:
Code:
<!-- vbml: my_vbml_command -->
Your app will receive "my_vbml_command" in the ConvertVbmlToHtml event, where it can set the p_Html property to whatever you'd like to replace the comment with. VBML commands can also include parameters:
Code:
<!-- vbml: my_vbmlcommand(2, "Param") -->
The parameters will be passed in the po_VbmlParameters arraylist in the ConvertVbmlToHtml event, and you can use them however you like. Take a look at the Web/index.vbml file for examples of some VBML comments/commands, then look at the CApp class' mo_VbmlHelper_ConvertVbmlToHtml event sub to see how the VBML commands are processed.
To Try It Out Yourself:
IMPORTANT NOTE FOR LINUX/WINE USERS: Make sure to use an early Wine 5.x release or a Wine 7.x release. The late 5.x and 6.x series appears to have broken something related to networking, and the RC6 cWebServer class never receives data to respond to. This is discussed in more detail here.
- Make sure that all the RC6 DLLs are installed on your computer.
- Open VBWebAppServer.vbp and run it.
- In your browser, visit http://127.0.0.1:8080
You should see the following page:
Note that when running in the IDE, the server will be running as a single thread so performance won't be spectacular as each request will have to wait for the previous request to complete. You can however compile the EXE and use the /spawn switch to spawn as many app server listeners as you like. You can then put Nginx in front of the app server and configure it to be a reverse proxy to all your app server listeners.
Here's the code that produces the dynamic portions of the demo page:
Code:
Option Explicit
Private WithEvents mo_VbmlHelper As CAppHelperVbml
Public Sub RespondToRequest(po_Req As CHttpRequest, po_Response As CHttpResponse, po_Helpers As CAppHelpers)
Dim l_VisitCount As Long
With po_Req.Cookies
l_VisitCount = .CookieValueByKeyOrDefaultValue("visitcount", 0)
l_VisitCount = l_VisitCount + 1
.AddOrReplaceCookie "visitcount", l_VisitCount, , , Now + 10000
End With
With po_Response
If po_Helpers.Regex.Test(po_Req.Url(urlsection_Path), "^showcase/[0-9]+$", False) Then
' Get requested showcase image from database by numeric id
With New_C.Connection(pathApp & "web.sqlite", DBOpenFromFile)
With .CreateSelectCommand("SELECT image, etag, extension FROM showcase WHERE id=?")
.SetInt32 1, Split(po_Req.Url(urlsection_Path), "/")(1) ' Get image ID from request and use it for SELECT query
With .Execute(True)
If .RecordCount = 0 Then
' No image found!
po_Response.Send404NotFound
Else
' Found an image. Check to see if requester has a cached copy
If po_Req.Headers.HeaderValue("If-None-Match") = .Fields("etag").Value Then
' Requester has a cached copy, send 304 Not Modified to save bandwidth
po_Response.Send304NotModified
Else
' Requester does not have a cached copy of the image, so send it (along with the ETag so future cache hits can be tested).
po_Response.AddHttpHeader "ETag", .Fields("etag").Value
po_Response.SendSimpleByteArrayResponse .Fields("image").Value, , , mimeTypeFromFilePath(.Fields("extension").Value)
End If
End If
End With
End With
End With
Else
If Not New_C.FSO.FileExists(po_Req.LocalPath) Then
' File Not found!
.Send404NotFound
Else
If LCase$(Right$(po_Req.Url(urlsection_Path), 5)) = ".vbml" Then
' Request for a dynamic .vbml page
Set mo_VbmlHelper = po_Helpers.Vbml ' Pass VBML helper to module level variable to receive events.
.SendSimpleHtmlResponse mo_VbmlHelper.ParseVbmlString(New_C.FSO.ReadTextContent(po_Req.LocalPath)), po_Req.Cookies
Else
' Since we have auto serve enabled, we should never get here
' as the auto-serve feature should have found and served the requested file.
Debug.Assert False
.Send400BadRequest
End If
End If
End If
End With
End Sub
Private Sub mo_VbmlHelper_ConvertVbmlToHtml(ByVal p_VbmlCommand As String, ByVal po_VbmlParameters As RC6.cArrayList, p_Html As String, p_ShouldEscapeHtml As e_HtmlEscapeType)
Dim l_Date As Date
Dim l_ShowcaseCount As Long
Select Case p_VbmlCommand
Case "get_rc6_version"
' Get the file version of RC6.dll for reporting the most recent version
p_Html = New_C.Version
Case "get_rc6_date"
' Get the file creation date of RC6 DLL for reporting the most date of the most recent release
New_C.FSO.GetFileAttributesEx pathSystem & "RC6.dll", , , , l_Date
p_Html = Format$(l_Date, "YYYY-MM-DD")
Case "get_copyright"
' Get the copyright text for the page
p_Html = "Copyright " & Year(Now) & " — Olaf Schmidt."
p_ShouldEscapeHtml = htmlescape_No
Case "get_random_showcase_items"
' Get random RC6 showcase items and build the product showcase card.
' You can pass a count parameter with this command to determine the number of random showcase items to retrieve
l_ShowcaseCount = 2 ' Default to 2 showcase items
If po_VbmlParameters.Count > 0 Then l_ShowcaseCount = po_VbmlParameters.Item(0) ' Get the desired # of showcase items if defined.
With New_C.Connection(pathApp & "web.sqlite", DBOpenFromFile)
With .OpenRecordset("SELECT rowid, product_name, developer, description_html, website FROM showcase ORDER BY random() LIMIT " & l_ShowcaseCount)
Do Until .EOF
p_Html = p_Html & "<div class='card p-4'>" & _
"<h2 class='text-center'>" & htmlEscape(.Fields("product_name")) & "<br>by " & htmlEscape(.Fields("developer")) & "</h2>" & _
"<img alt='" & htmlEscape(.Fields("product_name")) & " Screenshot' style='max-height: 150px;' class='img-fluid mt-4 mb-4 mx-auto' src='showcase/" & htmlEscape(.Fields("id")) & "' />" & _
.Fields("description_html") & _
"<p><a href='" & htmlEscape(.Fields("website")) & "'>Learn more about " & htmlEscape(.Fields("product_name")) & "...</a></p>" & _
"</div>"
.MoveNext
Loop
End With
End With
p_ShouldEscapeHtml = htmlescape_No
Case Else
p_Html = "Unhandled VBML Command: " & p_VbmlCommand
Debug.Print p_Html
'Debug.Assert False
End Select
End Sub
You can see it's pretty standard VB6 code, reasonably readable/understandable and concise (62 lines not including comments).
Command Line Parameters
If you compile the EXE you'll have access to some command line parameters:
/spawn <number>
Start the app server in "spawner" mode which will cause it to launch <number> processes in "listener" mode.
/stop
Stop all listener and spawner processes.
/ip <IPv4 address>
Tells the app server what IP to listen on
/port <Port>
Tells the app server what Port to listen on. When used with /spawn, this will be the first port of the first spawned listener. Additonal spawned listeners will listen on <port+spawnindex>. For example, spawning 3 listeners at base port 8080 with the command /spawn 3 /ip 127.0.0.1 /port 8080 will result in listeners on ports 8080, 8081, and 8082.
/rootpath <folder path>
Tells the server where the root folder is for serving static files. This defaults to the App.Path & "\web" folder. All of your static files should be placed in this folder (or subfolders thereof).
It's recommended to start in spawner mode like this:
Code:
VbWebApp.exe /spawn 10 /ip 127.0.0.1 /port 8080
The above command spawns 10 app listeners on ports 8080-8089.
Note that the compiled EXE expects the RC6 DLLs to be in the App.Path & "\System" folder for reg-free use.
Anyway, I hope some of you find this useful, and I'll be happy to answer any questions you might have.
SOURCE CODE HERE: VBWebAppServer14.zip
Last edited by jpbro; Jan 15th, 2022 at 02:35 PM.
-
Oct 29th, 2021, 05:15 PM
#2
Re: VB6 Web Site/App Server
-
Oct 29th, 2021, 05:16 PM
#3
Re: VB6 Web Site/App Server
Also reserved for future use.
-
Oct 29th, 2021, 09:03 PM
#4
Addicted Member
Re: VB6 Web Site/App Server
G'Day JPBro
Thanks for this post, very interesting and like all of your posts real quality.
But, I'm having what I fear is going to be a very simple mistake.
I cannot compile the project and I think it is to do with my RC6 environment.
I have
- Copied the dlls to System folder under App folder
- Registered RC6.dll & added to project refs.
- Registered RC6Widgets.dll & added to project refs.
As you probably remember I tried to get VB6 going as a Web Dev. 'Engine' a few years back and this is another example of just not being able to get started !!!
H E L P -
Attachment 182814
-
Oct 29th, 2021, 09:20 PM
#5
Re: VB6 Web Site/App Server
Hi jg.sa,
In the App\System folder, you should have the following files:
cairo_sqlite.dll
DirectCOM.dll
RC6.dll
(You don't need RC6Widgets.dll for this project).
RC6.dll should be registered on your development machine only (you won't need to register when deploying the app to other machines).
The VBWebAppServer.vbp should already have a reference to RC6.dll, and you should then be able to compile the software to the App folder at this point.
It sounds like you've done the right stuff, so I'm not really sure what's wrong. Unfortunately your attachment didn't work for me (it just says "Attachment 182814") so I can't see what error message you a re getting. Can you try posting the image again?
-
Oct 30th, 2021, 11:13 AM
#6
Re: VB6 Web Site/App Server
@jg.sa - I've made a few changes to the source that might help. Also be sure that you have downloaded and registered the latest version of RC6 (6.0.8). If there are still any problems, please re-post the screenshot or the full error message so I can have a better chance to figure out what's going wrong.
-
Oct 30th, 2021, 05:09 PM
#7
Hyperactive Member
Re: VB6 Web Site/App Server
very good work.
I will try it more calmly.
a greeting
-
Oct 31st, 2021, 10:44 AM
#8
Re: VB6 Web Site/App Server
I've just updated the source code in Post #1 with a small improvement when loading hundreds of app server listeners. Before the self-healing feature would chew up way too much CPU when checking hundreds of listeners. Now I'm break up the checks into chunks so that CPU usage is reasonable.
@yokesee - thanks, I hope you find the project useful.
-
Nov 9th, 2021, 05:03 PM
#9
Re: VB6 Web Site/App Server
Not sure if any one is bother to play around with this, but if you are please don't try it under Linux/Wine yet. I've bumped into an issue with the RC6 cWebServer under Linux/Wine and there's no sense with any of you wasting your time in that environment until it is resolved. Everything works fine on Windows (tested on 10 only so far, but should be good on any of the OSes that RC6 works with, which I believe is Win7+).
I'll be working on a small login/session handling example soon that I will post as soon as it is done.
-
Nov 9th, 2021, 05:15 PM
#10
Re: VB6 Web Site/App Server
Originally Posted by jpbro
Not sure if any one is bother to play around with this, but if you are please don't try it under Linux/Wine yet. I've bumped into an issue with the RC6 cWebServer under Linux/Wine and there's no sense with any of you wasting your time in that environment until it is resolved. Everything works fine on Windows (tested on 10 only so far, but should be good on any of the OSes that RC6 works with, which I believe is Win7+).
You should update your OP with this new information. Remember a lot of lurkers come here too, many times led directly by Google's search engines. For example this thread I made back 2012 has something like 12000+ views. All of that can't be from members only. We members will tend to read all of the posts in a thread but some random wanderer from the wider internet may not read past the OP. Just a small tip
-
Nov 9th, 2021, 05:29 PM
#11
Re: VB6 Web Site/App Server
Sure, makes sense & will do, done.
-
Nov 10th, 2021, 01:04 AM
#12
Addicted Member
Re: VB6 Web Site/App Server
G'Day Bro
Now I can compile
A N D
Run in IDE
Hugh round of applause !!!
You are the guru
-
Nov 10th, 2021, 08:10 AM
#13
Re: VB6 Web Site/App Server
@jg.sa - Great, glad you are up and running, and I hope you find the app useful. If you encounter any bugs or issues, please feel free to post here.
-
Nov 10th, 2021, 10:43 AM
#14
Re: VB6 Web Site/App Server
Quick and important update for Linux/Wine users: Make sure to use a Wine 5.x release. The 6.x series appears to have broken something related to networking, and the RC6 cWebServer class never receives data to respond to.
I'm looking for a way to get up and running on 6.x, we'll see if I get lucky.
-
Nov 10th, 2021, 10:56 AM
#15
Re: VB6 Web Site/App Server
Perhaps there is something wrong on the Wine side of things. Perhaps there is a forum somewhere where you can alert the developers of Wine that it has a problem. You may also want to alert Olaf just in case the problem is in RC6. I doubt it but it's possible.
-
Nov 10th, 2021, 11:01 AM
#16
Re: VB6 Web Site/App Server
I believe that's the case. There is a Wine forum so I will start a thread there when I have a chance. The Wine devs require a mountain of evidence, so it will take some time to gather it.
-
Nov 11th, 2021, 01:32 PM
#17
Re: VB6 Web Site/App Server
Alright, after much deeper testing I'm fairly confident that the bug is with Wine 6.x. I've submitted the bug report here: https://bugs.winehq.org/show_bug.cgi?id=52024, so hopefully I'm right and haven't wasted the Wine dev's time!
-
Nov 12th, 2021, 08:05 PM
#18
Addicted Member
Re: VB6 Web Site/App Server
G'Day Bro
I will 1stly mention what I'm trying to achieve. I want to be able to create smart 'Contact Us' forms, which will include fields like "Employee / Contractor / Contact' email address, so the form can route to a particular inside enterprise person, without having the 'Web Master' forward the email that resulted from this web page.
So I'm hoping to eventually parameterize these types of forms.
I see you mention - "Safe" DB creation
Is this something that you designed into your code, when I read thru. the code it seems to be a part of RC.
If that is the case, what would be the best way to handle forms like 'Contact Us'.
As VB is so good with strings I was hoping to us split to pull apart or assemble the field values and eventually dev. generic fields processing routines for web forms.
TIA
-
Nov 13th, 2021, 05:14 PM
#19
Re: VB6 Web Site/App Server
@jg.sa
I just uploaded the ZIP in the first post with a small demonstration of how you might implement a dynamic contact form. What it does:
1) Converts a VBML tag (get_contact_form) into an HTML <form> block.
2) Queries a DB for available types of issues (e.g. Bug Report, Feature Request).
3) Accepts submission from the user, and determines what email addresses should receive the user's comments depending on the issue type. E.g. bug reports go to certain contacts, feature requests go to different contacts.
4) Fixes a bug in form query data handling.
What it doesn't do:
1) It doesn't actually send the email. That is outside the scope of the demo.
So if you go ahead and grab the latest sources and run it, you can go to http://127.0.0.1:8080 and scroll down to the bottom of the page to see this:
Fill in the email address & comments, then click submit. You see a plain text page confirming who the email was "sent" to. If you go back and change the issue type and re-submit, you will see different recipients have been "sent" an email.
Here's the code added to the ConvertVbmlToHtml event of the CApp class:
Code:
Case "get_contact_form"
' Build a dynamic contact form based on records in the "contact_issues" table of our web DB.
' When the user submits this form, the RespondToRequest event will be fired.
' The form query data will be held in the po_Req.Query object
' The value keys will be:
' issue_id - The row ID of the selected contact_issues record
' email - The submitter's email address
' comments - The submitter's comments
With New_C.Connection(pathApp & "web.sqlite", DBOpenFromFile)
With .OpenRecordset("SELECT id, issue_name FROM contact_issues")
p_Html = "<h1>Contact Form</h1>" & _
"<form action='contact' method='post'>" & _
"<select name='issue_id'>"
' Build issue types drop-down list
Do Until .EOF
p_Html = p_Html & _
"<option value='" & .Fields("id").Value & "'>" & htmlEscape(.Fields("issue_name").Value) & "</option>"
.MoveNext
Loop
p_Html = p_Html & "</select>"
' Add fields for submitter's email address and comments.
p_Html = p_Html & "<p><label>Your Email</label></p><p><input type='email' name='email'></p>" & _
"<p><label>Your Comments</label></p><textarea name='comments'></textarea></p>" & _
"<button type='submit'>Submit</button>"
p_Html = p_Html & "</form>"
End With
End With
And here's the code added to the RespondToRequest event:
Code:
Select Case LCase$(po_Req.Url(urlsection_Path))
Case "contact"
' The contact form has been submitted.
' Get the comma-separated email list from our web DB and send the email to all contacts in the list.
' NOTE: We aren't actually going to send the emails in this demo as it is outside the scope of this project.
With New_C.Connection(pathApp & "web.sqlite", DBOpenFromFile)
With .OpenRecordset("SELECT emails FROM contact_people WHERE issue_id=" & po_Req.Query("issue_id"))
Dim l_Emails As String
l_Emails = .Fields("emails").Value
End With
End With
' In a real app we'd redirect to a nice HTML page (or show a popup) to tell the user the email was sent.
' For demo purposes, we'll just send back some boring plain text.
.SendSimplePlainTextResponse "Thank you, your message has been sent to: " & vbNewLine & vbNewLine & Replace$(l_Emails, ",", vbNewLine)
Case Else
' Code below this point is unchanged from the previos demo
Hope that helps
-
Nov 13th, 2021, 05:21 PM
#20
Re: VB6 Web Site/App Server
Also re: the CSafeDB class - it's not needed for your scenario if you are creating the Contact Form DB/tables offline (that is, not creating them live in a running app server instance).
The "Safe" part comes from the fact that it puts the opening of a DB connection behind a mutex, ensuring that you can create a DB & add tables etc... in one process, and if another process tries to open it while the first process is busy, the second process will wait until the DB has been completely setup before it will be allowed to grab a connection. Since the CAppServer is designed to run as multiple processes for serving requests, we want to make sure they aren't stepping on each other when creating a DB (only one process will be allowed to create a specific DB even if multiple processes are racing to do it).
-
Nov 13th, 2021, 06:40 PM
#21
Hyperactive Member
Re: VB6 Web Site/App Server
Very good work, keep it up.
the examples work fine.
I get the following errors on the console, but it seems to work all fine.
I run the cmd VBWebAppServer.exe / spawn 5
Code:
***ERROR: -2147221504 An instance is already running at 0.0.0.0:8084
***ERROR: -2147221504 An instance is already running at 0.0.0.0:8081
a greeting
-
Nov 13th, 2021, 06:45 PM
#22
Re: VB6 Web Site/App Server
Hi yokesee,
Thanks for reporting the issue with the already running instance message. So far I have been unable to reproduce the problem, so I'm not sure why you are seeing that message. If you look at the Task Manager, do you have 6 VbWebAppServer.exe instances running (1 for the spawner/monitor process, and 5 for the spawned listener processes)?
-
Nov 13th, 2021, 06:52 PM
#23
Re: VB6 Web Site/App Server
Forgot to mention that the latest version has a small improvement to the CHttpCookies and CHttpQueryParams classes.
In the older version you had to use this fairly long code to access a query param value:
Code:
MsgBox po_Req.Query.ValuesByKey("paramname").ValueByIndex(0)
That was getting tiring, so there's a new hidden default .Values(KeyOrIndex) method in the CHttpQueryParams class, and a new hidden default .FirstValue method in the CHttpQueryParam class. Since you will only have 1 query parameter value per query parameter key 99.999% of the time, this means we can now shorten access to a particular query param value as follows:
Code:
MsgBox po_Req.Query("paramname")
Similarly for Cookies, you can use the new shorthand:
Code:
Msgbox po_Req.Cookies("cookiename")
-
Nov 13th, 2021, 08:10 PM
#24
Re: VB6 Web Site/App Server
@yokesee - I have now been able to reproduce the problem you reported with error messages in the console. It seems to happen after a period of time with the monitor incorrectly trying to respawn instances it thinks are dead but are actually still alive. Clearly a bug in my code somewhere, so I will get it fixed ASAP. Thanks for reporting the problem!
-
Nov 13th, 2021, 08:14 PM
#25
Hyperactive Member
Re: VB6 Web Site/App Server
thank you very much great job as always
-
Nov 13th, 2021, 08:22 PM
#26
Addicted Member
Re: VB6 Web Site/App Server
G'Day Bro
Thank you , Thank you , Thank you !!!
This example is so much more than I had hope for and as I'm in the middle of a family BBQ I should not be looking at code.
But I have this on the bottom of the updated example
"Unhandled VBML Command: get_contact_form"
Don't rush to fix this as I can see why, just can't provide a fix as I'm under 'Pressure' not to turn Kebabs into charcoal
Case Else
p_Html = "Unhandled VBML Command: " & p_VbmlCommand
Debug.Print p_Html
'Debug.Assert False
End Select
-
Nov 13th, 2021, 08:56 PM
#27
Re: VB6 Web Site/App Server
If you're running the EXE, please make sure you've recompiled it so that the new "get_contact_form" handling code is compiled.
If you're running from the IDE, can you confirm that there is code that looks like this in the mo_VbmlHelper_ConvertVbmlToHtml method of the CApp class?
Code:
Case "get_contact_form"
' Build a dynamic contact form based on records in the "contact_issues" table of our web DB.
' When the user submits this form, the RespondToRequest event will be fired.
' The form query data will be held in the po_Req.Query object
' The value keys will be:
' issue_id - The row ID of the selected contact_issues record
' email - The submitter's email address
' comments - The submitter's comments
With New_C.Connection(pathApp & "web.sqlite", DBOpenFromFile)
With .OpenRecordset("SELECT id, issue_name FROM contact_issues")
p_Html = "<h1>Contact Form</h1>" & _
"<form action='contact' method='post'>" & _
"<select name='issue_id'>"
' Build issue types drop-down list
Do Until .EOF
p_Html = p_Html & _
"<option value='" & .Fields("id").Value & "'>" & htmlEscape(.Fields("issue_name").Value) & "</option>"
.MoveNext
Loop
p_Html = p_Html & "</select>"
' Add fields for submitter's email address and comments.
p_Html = p_Html & "<p><label>Your Email</label></p><p><input type='email' name='email'></p>" & _
"<p><label>Your Comments</label></p><textarea name='comments'></textarea></p>" & _
"<button type='submit'>Submit</button>"
p_Html = p_Html & "</form>"
End With
End With
Enjoy the BBQ
-
Nov 13th, 2021, 10:41 PM
#28
Re: VB6 Web Site/App Server
@yokesee, I've figured out why you are seeing the error message in the console.
When you don't specify an IP address to listen to, the software defaults to meta-address 0.0.0.0. This is OK for the "listener" mode since 0.0.0.0 means "listen on any/all interfaces", but it is bad for the monitor code since it can't connect to 0.0.0.0 to confirm the server is still listening. It subsequently thinks the server is broken and tries to restart it, but the restart fails because the server is actually OK.
I've changed the code to pick a valid local IP address using a RC6 cTcpClient.GetIP("") call when the listen address is 0.0.0.0 so that the monitor can connect and confirm that the listener is responding to requests. The latest version is available in the first post.
Thanks again for reporting the problem!
Last edited by jpbro; Nov 13th, 2021 at 11:24 PM.
-
Nov 13th, 2021, 11:24 PM
#29
Addicted Member
Re: VB6 Web Site/App Server
G'Day Bro
I have just 'escaped' to get a couple of brewsky from the fridge.
I should have thought about rebuilding the image !!!
We are going to have to agree a data structure for handling forms in the future, nothing complicated possibly using .ini files and compiler directives, I can do this and submit for 'approval' !!!
-
Nov 13th, 2021, 11:29 PM
#30
Re: VB6 Web Site/App Server
In the demo app, I use a database for configuring the dynamic aspects of the form. I've only done the bare minimum just to demonstrate it is possible to create custom forms/back-end routing. The EXE rebuild shouldn't generally be necessary, only if you add new features that the old compiled EXE won't understand. So yeah, decide on a structure/set of rules that will accommodate all of your business needs first, then work that into the compiled part. Once that's done you should be able to add forms, changes contacts, etc... without needing to recompile.
Anyway, I'm off to bed, so have a good night and a brewsky for me
-
Nov 14th, 2021, 01:55 PM
#31
Hyperactive Member
Re: VB6 Web Site/App Server
Very good work now it works perfectly.
take a little time to test, it has a lot of potential.
a greeting
-
Nov 14th, 2021, 02:09 PM
#32
Re: VB6 Web Site/App Server
Great, glad it's working better now and thanks for letting me know.
-
Nov 14th, 2021, 09:21 PM
#33
Hyperactive Member
Re: VB6 Web Site/App Server
it seems vbml is just html file, why not just use html file?
-
Nov 14th, 2021, 09:51 PM
#34
Addicted Member
Re: VB6 Web Site/App Server
G'Day Loquat
Bro is taking a break, so I'm southern hemisphere support
The official line is "Working as designed" - so 'Yes' not .html, but .vbml, which I really like, it is Bro's version of .php ( Pre-Processing )
Just my 2cs worth
-
Nov 14th, 2021, 11:05 PM
#35
Re: VB6 Web Site/App Server
Thanks for the support @jg.sa! You're 99% correct, but I'd like to clarify that VBML has a *much* smaller scope that PHP. I've never used PHP but AFAIK it is a Turing-complete language that is embedded into comments in HTML files.
VBML's scope is much more limited. While it is also embedded into comments in HTML files, it is only a "hook" into your VB6 code via this VBWebAppServer project. VBML is essentially a keyword and some optional parameters that can be sent to a VBWebAppServer hosted class for dynamic conversion to HTML "snippets" that will replace the HTML/VBML comment. The combined document will be served back to the requesting browser as HTML. The idea is to spend as much time as possible coding the dynamic parts of a web page in VB6, and as much time as possible coding the static parts in HTML.
For the visually minded:
Last edited by jpbro; Nov 14th, 2021 at 11:13 PM.
-
Dec 24th, 2021, 04:25 PM
#36
Re: VB6 Web Site/App Server
Some good news on the Wine front - Zebediah Figura has fixed the problem with 6.x, so I suspect an update will be coming soon. More info here: https://bugs.winehq.org/show_bug.cgi?id=52024
-
Dec 24th, 2021, 05:13 PM
#37
Re: VB6 Web Site/App Server
A little Christmas present for you all!
I've added a very simple LogIn/LogOut process to the page/app:
Logging in doesn't really do anything, it's just an example showing the use of Cookies and the new CAppHelperUsers class.
There's one user included with the demo, email: test@test.com, password: password
There are also a few bug fixes in the latest version (link is in the first post).
Enjoy!
-
Dec 24th, 2021, 06:28 PM
#38
Re: VB6 Web Site/App Server
Originally Posted by jpbro
Wow, thanks to the both of you...
(you really hung in there, compiling wine, making bisections + nice communication, BTW)
Olaf
-
Dec 24th, 2021, 06:49 PM
#39
Re: VB6 Web Site/App Server
Thanks Olaf, it was definitely a learning experience. Good thing Zebediah had a clue as to where the bug was though, I think it would have taken me a few more months to get there bisecting!
-
Dec 24th, 2021, 07:05 PM
#40
Re: VB6 Web Site/App Server
Some notes on the new CAppHelperUsers class. It has the following methods (which should all be fairly self-explanatory):
Code:
Public Function CreateUser(ByVal p_EmailAddress As String, ByVal p_DisplayName As String, ByVal p_Password As String) As String
Call this method to create a new user account. The account will be given a permission level of "unauthenticated" to start. Returns a unique user ID. You should probably keep this on the server side.
Code:
Public Function IsUserKnown(ByVal p_EmailAddress As String) As Boolean
Returns True if a user exists in the users.sqlite database users table. Otherwise returns False.
Code:
Public Function IsUserAuthenticated(ByVal p_EmailAddress As String) As Boolean
Returns True if the user has been authenticated (for example, by clicking a link in an email or copy & pasting a code that you send them. You will have to implement this part yourself).
Code:
Public Function IsUserLoggedIn(ByVal p_UserIdOrEmailAddress As String, ByVal p_SessionToken As String) As Boolean
Returns True if the user is logged into an active session. Otherwise returns False.
Code:
Public Function LoginUser(ByVal p_EmailAddress As String, ByVal p_Password As String) As String
Call to login a user by their email address & password. Returns a unique session token that should be sent to the client in a Cookie.
Code:
Public Function LogoutUser(ByVal p_EmailAddress As String) As Boolean
Call the log a user out of all their sessions.
Code:
Public Function LogoutSession(ByVal p_SessionToken As String) As Boolean
Call to log a user out of a single session (the session token will usually be stored in a Cookie).
Code:
Public Function IsSessionActive(ByVal p_SessionToken As String) As Boolean
Returns True if a particular session is active/not expired. Otherwise returns False.
Code:
Public Property Get UserPermissionLevel(ByVal p_EmailAddress As String) As e_UserPermissionLevel
Returns a user's account permission level. Possible values are:
Code:
userpermissionlevel_Banned = -1
userpermissionlevel_Unknown = 0
userpermissionlevel_Unauthenticated = 1
userpermissionlevel_Normal = 2
userpermissionlevel_SuperAdmin = &H7FFFFFFF
Code:
Public Property Let UserPermissionLevel(ByVal p_EmailAddress As String, ByVal p_PermissionLevel As e_UserPermissionLevel)
Sets a user's permission level. Use one of the enum values shown above.
Code:
Public Property Get UserInfoFromSessionToken(ByVal p_SessionToken As String, Optional ByVal p_GetIfExpired As Boolean) As CUserInfo
Get a CUserInfo class (by unique session token) with all of a user's account info.
Code:
Public Sub ActionPerformed(ByVal p_SessionToken As String)
Call whenever the user requests something from the server to keep their session alive. Sessions will expire after 1800 seconds currently, but I will likely make this configurable.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|