Page 1 of 3 123 LastLast
Results 1 to 40 of 108

Thread: VB6 Web Site/App Server

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.


    1. Make sure that all the RC6 DLLs are installed on your computer.
    2. Open VBWebAppServer.vbp and run it.
    3. In your browser, visit http://127.0.0.1:8080


    You should see the following page:

    Name:  rc6web.jpg
Views: 492066
Size:  40.8 KB

    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) & " &mdash; 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.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    Re: VB6 Web Site/App Server

    Reserved for future use

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    Re: VB6 Web Site/App Server

    Also reserved for future use.

  4. #4
    Addicted Member jg.sa's Avatar
    Join Date
    Nov 2017
    Location
    South Australia ( SA )
    Posts
    198

    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

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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?

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

  7. #7
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    506

    Re: VB6 Web Site/App Server

    very good work.
    I will try it more calmly.
    a greeting

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

  10. #10
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: VB6 Web Site/App Server

    Quote Originally Posted by jpbro View Post
    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
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    Re: VB6 Web Site/App Server

    Sure, makes sense & will do, done.

  12. #12
    Addicted Member jg.sa's Avatar
    Join Date
    Nov 2017
    Location
    South Australia ( SA )
    Posts
    198

    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

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

  14. #14

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

  15. #15
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    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.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  16. #16

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

  17. #17

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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!

  18. #18
    Addicted Member jg.sa's Avatar
    Join Date
    Nov 2017
    Location
    South Australia ( SA )
    Posts
    198

    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

  19. #19

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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:

    Name:  2021-11-13_17-14-12.jpg
Views: 1319
Size:  20.3 KB

    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

  20. #20

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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).

  21. #21
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    506

    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

  22. #22

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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)?

  23. #23

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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")

  24. #24

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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!

  25. #25
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    506

    Re: VB6 Web Site/App Server

    thank you very much great job as always

  26. #26
    Addicted Member jg.sa's Avatar
    Join Date
    Nov 2017
    Location
    South Australia ( SA )
    Posts
    198

    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

  27. #27

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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

  28. #28

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

  29. #29
    Addicted Member jg.sa's Avatar
    Join Date
    Nov 2017
    Location
    South Australia ( SA )
    Posts
    198

    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' !!!

  30. #30

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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

  31. #31
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    506

    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

  32. #32

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    Re: VB6 Web Site/App Server

    Great, glad it's working better now and thanks for letting me know.

  33. #33
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: VB6 Web Site/App Server

    it seems vbml is just html file, why not just use html file?

  34. #34
    Addicted Member jg.sa's Avatar
    Join Date
    Nov 2017
    Location
    South Australia ( SA )
    Posts
    198

    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

  35. #35

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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:

    Name:  VBML Flow(1).jpg
Views: 1395
Size:  34.5 KB
    Last edited by jpbro; Nov 14th, 2021 at 11:13 PM.

  36. #36

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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

  37. #37

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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:

    Name:  2021-12-24_16-30-21.jpg
Views: 1252
Size:  19.2 KB

    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!

  38. #38
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: VB6 Web Site/App Server

    Quote Originally Posted by jpbro View Post
    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
    Wow, thanks to the both of you...
    (you really hung in there, compiling wine, making bisections + nice communication, BTW)

    Olaf

  39. #39

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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!

  40. #40

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    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.

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width