-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
Niya
That error looks pretty clear. It looks like he is running multiple instances and your project is checking for that.
There's a "watchdog" running in the spawner class that checks periodically to make sure that the listener classes have bound to the network adapter and are serving data. After a certain number of failures, the watchdog will kill the apparently broken listener process and restart it. If port 5000 works, but port 8080 doesn't, then I suspect that something else is already listening on port 8080 and that's why it is failing.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
sergeos
Yes, http is work!
but only on 5000 port.
8080 don't work.
If port 5000 works, but port 8080 doesn't, then I would suspect that there's another application already running that is using port 8080. Can you confirm whether or not this is the case?
Quote:
After command /stop also don't work.
Do you get any error messages when running /stop? Does /stop work when running listeners on port 5000 and fail when running listeners on port 8080, or does /stop never work?
-
Re: VB6 Web Site/App Server
Use netstat -b -n in command prompt or SysInternals TCPView to find which program is using the port. No need to guess when there are tools.
-
Re: VB6 Web Site/App Server
I have found a couple of issues that need addressing with the watchdog, so I will have a fix for those soon.
I'm also trying to find a good way to determine if a port is already in use when I attempt to spawn a listener on such a port. It looks like the RC6 cWebServer.Listen method doesn't raise an error (or have a return value to test) when it tries to bind to an ip/port that is already bound to another app. I've tried using the RC6 cTcpClient object, but the Connect method always returns a hSocket (even when there's nothing listening on the port I'm trying to connect to). cTcpClient.SendData looks like it should do the trick - it does timeout after about 5 seconds if there's nothing actually listening on the port, but I'm not sure I want to wait 5 seconds for each CAppServer class to come online (if I can help it). Anyway, I'll continue trying to see if I can figure out a better way to do this.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
I'm also trying to find a good way to determine if a port is already in use when I attempt to spawn a listener on such a port. It looks like the RC6 cWebServer.Listen method doesn't raise an error (or have a return value to test) when it tries to bind to an ip/port that is already bound to another app.
This is alarming. It should raise an error when trying to listen on a Port/IP combo that is already in use. I think Olaf should be notified of this because this is quite serious in my opinion.
-
Re: VB6 Web Site/App Server
I sent him a PM. Hopefully he can look into it for you or suggest something you haven't thought of.
-
Re: VB6 Web Site/App Server
I think it might be by design actually, using a non-blocking connection that returns immediately. I don't know enough about winsock programming to be sure, but there's a call to the ws2_32.connect function that explicitly ignores error 10035 (WSAEWOULDBLOCK), assumably on the presumption that the connection will eventually succeed.
I think I'll have to roll my own "blocking" connection: https://docs.microsoft.com/en-us/cpp...?view=msvc-170. Maybe a "blocking" mode property on the cTcpClient object would be a nice addition though.
-
Re: VB6 Web Site/App Server
The RC6 cWebServer object uses a cTcpServer object under the hood. The cTcpServer object uses the SO_REUSEADDR socket option, and that means the bind will "succeed" no matter what (but then the behavior for all sockets bound to that port is indeterminate).
Interesting article about SO_REUSEADDR here: https://docs.microsoft.com/en-us/win...clusiveaddruse Interesting snippet from that article:
Quote:
The exception to this non-deterministic behavior is multicast sockets. If two sockets are bound to the same interface and port and are members of the same multicast group, data will be delivered to both sockets, rather than an arbitrarily chosen one.
...
The SO_REUSEADDR option has very few uses in normal applications aside from multicast sockets where data is delivered to all of the sockets bound on the same port. Otherwise, any application that sets this socket option should be redesigned to remove the dependency since it is eminently vulnerable to "socket hijacking". As long as SO_REUSEADDR socket option can be used to potentially hijack a port in a server application, the application must be considered to be not secure.
At this point I'm a bit out of my depth, but maybe a cTcpServer option to use SO_EXCLUSIVEADDRUSE would be another useful addition to RC6? I defer to Olaf's expertise here.
-
Re: VB6 Web Site/App Server
Well I'll say this, in my experience writing normal Unicast Winsock applications in both VB6 and .Net, an error is supposed to be thrown when you try to listen on a port/IP combination that another server is already listening on locally. This is the behavior I expect and what I'm used to. Perhaps there is something going on here I'm not familiar with.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
Yep, a bit further down the article even describes, why I've introduced the ReUse-Option:
This issue can become complicated because the underlying transport protocol may not terminate the connection...
It is possible that the underlying transport protocol might never release the connection
At the time I've developed this (and used it intensively in different scenarios, with the RPCServer-Classes of the RichClient),
having the ReUse-Option in place, ensured a much better "restart-behaviour" of the services.
But this was in the era, where "XP/W2K" machines were common -
perhaps such "hanging connections" (which can occur for all kind of reasons) -
are detected by the modern OSes much earlier these days, so that a restart of such a Listener-Process -
is not "doomed with constant failing" for longer time-intervals (as it was in the XP/W2k era).
Quote:
Originally Posted by
jpbro
At this point I'm a bit out of my depth, but maybe a cTcpServer option to use SO_EXCLUSIVEADDRUSE would be another useful addition to RC6? I defer to Olaf's expertise here.
I could send you an early release of the RC6 (I'm still not yet done with the big one I've planned with the new SQLite-version) -
in which I've switched the setsockopt-Call in the Listen-Method to SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR -
(doing "two steps" forward, so to say).
Olaf
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
Schmidt
At the time I've developed this (and used it intensively in different scenarios, with the RPCServer-Classes of the RichClient),
having the ReUse-Option in place, ensured a much better "restart-behaviour" of the services.
But this was in the era, where "XP/W2K" machines were common -
perhaps such "hanging connections" (which can occur for all kind of reasons) -
are detected by the modern OSes much earlier these days, so that a restart of such a Listener-Process -
is not "doomed with constant failing" for longer time-intervals (as it was in the XP/W2k era).
Ah yes, that makes sense. Since the older OSes aren't being targeted by RC6 any more, I guess there shouldn't be any issue moving to the newer SO_EXCLUSIVEADDRUSE listen method.
Quote:
Originally Posted by
Schmidt
I could send you an early release of the RC6 (I'm still not yet done with the big one I've planned with the new SQLite-version) -
in which I've switched the setsockopt-Call in the Listen-Method to SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR -
(doing "two steps" forward, so to say).
Thank you Olaf, but there's certainly no rush on my part. If you prefer to take your time to get the other big stuff done and release once, that's perfectly fine with me. Unless you would like me to test the SO_EXCLUSIVEADDRUSE change in case it might have some unintended side effects? I'm more than happy to do that, and I can even see how it goes under Linux/Wine.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
Niya
Well I'll say this, in my experience writing normal Unicast Winsock applications in both VB6 and .Net, an error is supposed to be thrown when you try to listen on a port/IP combination that another server is already listening on locally. This is the behavior I expect and what I'm used to. Perhaps there is something going on here I'm not familiar with.
That was what I assumed would happen, but it looks like the SO_REUSEADDR method had different ideas ;)
-
Re: VB6 Web Site/App Server
I've updated the source in the first post with the following changes:
1) My "watchdog" code that monitors spawned listener/server processes was totally brain-dead (only testing if it could connect & send data, not checking to see if it could receive data). This should now be fixed.
2) I've added a check to make sure the server ip/port that we are trying to bind to isn't already bound to another application. If it is, all app servers will be stopped. This is a stop gap measure while Olaf is working on the next RC6 release (which will use SO_EXCLUSIVEADDRUSE to bind to an adapter and fail if another app already is already bound as discussed here). Thank you for the prompt response Olaf! :)
-
Re: VB6 Web Site/App Server
Dear Sir,
can you provide an a little example with calculator page?
Just page with the texbox on it and with a button.
And when we are typed in to the textbox any simple expression (like, 2+2), click the button, and the server return to page a result of our expression.
Thank you very much!
-
Re: VB6 Web Site/App Server
Here's a very simple example that will evaluate formulas entered into your browsers address bar at the "evaluate/" path.
For example, if you go to https://127.0.0.1:8080/evaluate/24/(2/100), you will get a plain text response that looks like this:
Code:
Formula: 24/(2*100)
Result: 0.12
You will need to add the following code to the CApp class, after the "showcase/" block in the RespondToRequest event.
Code:
ElseIf po_Helpers.Regex.Test(po_Req.Url(urlsection_Path), "^evaluate/.+$", False) Then
' Found an "evaluate/" path. We will try to evaluate anything after the "evaluate/" part of the path.
' For example, visiting http://127.0.0.1:8080/evaluate/24*(2/100)
' Will return a text/plain response of:
' Formula: 24/(2*100)
' Result: 0.12
Dim l_EvaluateResult As Variant
Dim l_EvaluateError As String
Dim l_EvaluateFormula As String
' Strip "evaluate/" from the start of the path to get the formual
l_EvaluateFormula = Trim$(Mid$(po_Req.Url(urlsection_Path), Len("evaluate/") + 1))
' Strip trailing "/" if present in the formula to avoid division by 0 error
If Right$(l_EvaluateFormula, 1) = "/" Then l_EvaluateFormula = Left$(l_EvaluateFormula, Len(l_EvaluateFormula) - 1)
' Attempt to evaluate the formula
l_EvaluateResult = New_C.Formula.Evaluate(l_EvaluateFormula, l_EvaluateError)
If l_EvaluateError <> vbNullString Then
' There was an error evaluating the formula! So set the result to the error.
l_EvaluateResult = "*ERROR: " & l_EvaluateError
End If
' Return the formula and the result as plain text.
po_Response.SendSimplePlainTextResponse "Formula: " & l_EvaluateFormula & vbNewLine & "Result: " & l_EvaluateResult
IMPORTANT NOTE:It looks like the RC6 cWebServer class won't accept "+" in your URL path formulas. So for testing purposes for now, only use "-", "*", "/", and parentheses to test different formula evaluations. If you want try addition, instead of "+", use "%2B" in your formula (that will get converted to + on the server side).
Olaf - it looks like the URLDecode method always converts "+" to a space character, but I'm not sure that this is required? I tried a few online URLDecoders and some converted "+" to "-", but others didn't. A bit of research seems to indicate that "+" should be valid in URL paths, but possibly converted to " " in the query part of the URL. I take this to mean that a URL like this:
Code:
http://127.0.0.1:8080/evaluate/2+2?2+2
Should be decoded to:
Code:
http://127.0.0.1:8080/evaluate/2+2?2 2
That is, the first + in the path is left alone, but the second + in the query is converted to " ".
I say "possibly" for the above, because none of the browsers I tried auto-converted "+" to "%2B" anywhere in the URL, which seems to indicate that + is legal anywhere in a URL. The exception would be for x-form-urlencoded data submitted from a form that *does* use "+" to indicate " ".
I have to do a bit more research to be sure, but it does look like this has been a source of confusion in other languages/frameworks/etc...
A thought: Perhaps URLDecode/URLEncode should only be for x-form-urlencoded queries, not for URL paths handled by the cWebRequest class. cWebRequest should have it's own URLDecoding that skips the "+" to " " conversion. Or perhaps, URLDecode could have an optional parameter (PreservePlus) that cWebRequest and other callers can set to TRUE when they know they are dealing with URLs and not form data?
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
...it looks like the URLDecode method always converts "+" to a space character, but I'm not sure that this is required?
Interpreting a "+" as WitheSpace-Char, still seems "standard-behaviour"...
https://stackoverflow.com/questions/...ymbol-in-a-url
I guess, if somebody wants to make his own Formula-parsing WebAPI-function,
(passing the Formula in the URL), it is good advice, to perform (still at the clientside):
FormulaParam = New_c.Crypt.UrlEncode(TheFormulaString)
(or a javascript-equivalent, when triggered from a Browser).
Or pass the Formula-Param JSON-encoded in the Body (using a POST-Request).
Olaf
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
Schmidt
Interpreting a "+" as WitheSpace-Char, still seems "standard-behaviour"...
It does seem common, but I've tried some online URL decoders and not all convert + to " ".
According to the URI spec at w3.org, "+" is reserved as a shorthand notation for " " only within the query string:
Quote:
Query strings
The question mark ("?", ASCII 3F hex) is used to delimit the boundary between the URI of a queryable object, and a set of words used to express a query on that object. When this form is used, the combined URI stands for the object which results from the query being applied to the original object.
Within the query string, the plus sign is reserved as shorthand notation for a space. Therefore, real plus signs must be encoded. This method was used to make query URIs easier to pass in systems which did not allow spaces.
And according to RFC 3986 Appendix A, "+" is allowed in the scheme component of a URL:
Quote:
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
A naive +=" " approach would break the URL (in admittedly vanishingly small set of URLs in the real-world, though some surprisingly exist!).
Here's an interesting ticket with a similar report of Java's URLDecode method unexpectedly converting "+" to " ". It was closed as "not an issue" not because URLDecode was correctly decoding URLs, but because the documentation stated it should only be used for HTML form encoding/decoding, nor for URL encoding (LOL - don't use URLDecode for decoding URLs)!
Quote:
The Java API documentation at
https://docs.oracle.com/javase/8/doc...a/net/URL.html clearly states that "The URLEncoder and URLDecoder classes can also be used, but only for HTML form encoding, which is not the same as the encoding scheme defined in RFC2396." . This means that it is not meant for URL encoding and will cause issues with spaces and plus signs in the path.
Quote:
Originally Posted by
Schmidt
Or pass the Formula-Param JSON-encoded in the Body (using a POST-Request).
Agreed that this is a better approach. My example using the URL was just a "quick and dirty" attempt to demonstrate how you can evaluate a formula, not a recommended way to do it. But I think it exposed a shortcoming in the cWebResponse class' URL decoding.
If you don't want to change the cCrypt URLDecode method, because it may break existing code or because adding a new parameter will break binary compatibility, I understand completely. Would you instead consider one of the following two solutions:
1) Implement a separate URLDecode method for the cWebResponse class (I'll email a modified cCrypt URLDecode that could be used to try and save you some time)
OR
2) Add a RawUrl property to the cWebRequest class so we can perform our own RFC-compliant decoding?
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
1) Implement a separate URLDecode method for the cWebResponse class (I'll email a modified cCrypt URLDecode that could be used to try and save you some time)
OR
2) Add a RawUrl property to the cWebRequest class so we can perform our own RFC-compliant decoding?
Regarding 1):
The next release will have the following changes in cCrypt, cWebRequest and cWebResponse
(regading the UrlDecode Method-Signature, all using the same decoding-routine underneath):
Public Function URLDecode(U As String, Optional ByVal PlusSignToSpace As Boolean = True) As String
Meaning, that backward-compatibility is kept (the new Optional Param defaulting to True) -
but one can influence the PlusSign-Decoding now...
Regarding 2)
The new optional Param then allows in conjunction with the new Property cWebRequest.URLRaw,
a specific decoding (without rolling your own function), by using:
MyDecodedURL = Request.URLDecode(Request.UrlRaw, False)
HTH
Olaf
-
Re: VB6 Web Site/App Server
Thank you Olaf, the new changes are very much appreciated!
-
Re: VB6 Web Site/App Server
IMO the query string should not be escaped/decoded. My observations are that WinHttp converts query strings to utf-8 and encodes every byte with highest bit set using %XY in hex to be able to "smuggle" headers through 7-bit networks probably (no idea actually).
In WinHttpRequest object there are several options which control url *escaping* performed:
- WinHttpRequestOption_UrlEscapeDisable (default False) - if set does not call UrlEscape API for URL at all (incl. query string)
- WinHttpRequestOption_UrlEscapeDisableQuery (default True) - if set does not call UrlEscape API for query string only
- WinHttpRequestOption_EscapePercentInURL (default false) - if set uses URL_ESCAPE_PERCENT flag in both calls to UrlEscape above
After calls to UrlEscape always hex encodes bytes with high bit set (second/custom ANSI codepage) to %XY
I think URLs are a big mess already, probably would be best to make possible to submit to the http server *any* Unicode string in the query string with high fidelity i.e. convert to utf-8 and don't massage/process it too much.
For the first part of the URL all hope is lost already IMO, it's not possible to pass random Unicode strings so this is more restricted by design, more escaped as a consequence and more error prone (i.e. client requests something but server understands another path altogether is not uncommon).
Best would be to make the http server compatible win WinHttpRequest but this would require a large test harness to encompass all the nasty corner-cases.
cheers,
</wqw>
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
wqweto
IMO the query string should not be escaped/decoded. My observations are that WinHttp converts query strings to utf-8 and encodes every byte with highest bit set using %XY in hex to be able to "smuggle" headers through 7-bit networks probably (no idea actually).
Perhaps I've misunderstood - but I think we have to be prepared to decode the query string (and the rest of the URL) server-side, because most browsers will encode the path/query portion of the URL. For example, this (insane) URL entered into the address bar (in Firefox):
Code:
http://127.0.0.1:8080/"test"?x=ABC DEF+"12345"
Gets sent to the server encoded:
Code:
GET /%22test%22?x=ABC%20DEF+%2212345%22 HTTP/1.1
Are you suggesting the the server should decode it, but the application on the server-side should if it wants to?
Quote:
Originally Posted by
wqweto
I think URLs are a big mess already,
Ain't that the truth ;)
Quote:
Originally Posted by
wqweto
probably would be best to make possible to submit to the http server *any* Unicode string in the query string with high fidelity i.e. convert to utf-8 and don't massage/process it too much.
Sounds like the new URLRaw property will do that, and allow the server-side app to deal with URLs (exactly as passed) however they see fit.
-
1 Attachment(s)
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
Here's a very simple example that will evaluate formulas entered into your browsers address bar at the "evaluate/" path.
Andt how do it not through a query string, but through a simple html (or, VBML) page, as if the user is entering text?
so the plan is:
- 1) the user follows the link /calculator
- 2) enters an expression in the text box
- 3) presses the button and the request goes to the our server
- 4) the server returns the result of the expression to this page
for example like here
Attachment 183585
Purely for understanding how the user interacts with the page and the server processes the received requests.
-
Re: VB6 Web Site/App Server
Can you post the HTML source for that page? I will show you what to put on the server side.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
Code:
http://127.0.0.1:8080/"test"?x=ABC DEF+"12345"
Gets sent to the server encoded:
Code:
GET /%22test%22?x=ABC%20DEF+%2212345%22 HTTP/1.1
The point is that the same URL using WinHttpRequest sends this to server
Code:
GET /%22test%22?x=ABC%20DEF+"12345" HTTP/1.1
. . . and the query string is somewhat *less* encoded than what chome does.
Probably both requests use valid URL encodings because a simple %XY decoder would not be bothered if both spaces and double-quotes are encoded and decode the same query string anyway.
Technically only % character has to be additionally escaped for a simple %XY decoder to produce valid query string. This query string should probably be treated as utf-8 encoded too.
cheers,
</wqw>
-
Re: VB6 Web Site/App Server
-
1 Attachment(s)
Re: VB6 Web Site/App Server
I've just updated the first post with a new version that includes my first pass at a CBuilderHtml class. This is a helper class that makes it a bit quicker/easier to build HTML documents and HTML snippets for serving from your web apps.
Here's a snippet from the demo app that builds and serves HTML when the browser requests the /virtualdoc/ path (e.g. http://127.0.0.1:8080/virtualdoc)
Code:
ElseIf po_Helpers.Regex.Test(po_Req.Url(urlsection_Path), "^virtualdoc(|/)$", False) Then
' Found a request for a "virtual" document
' We will build using the CBuilderHtml helper.
New_C.Timing True
With po_Helpers.Builders.Html.StartDoc ' Start an HTML5 document with the default parameters.
' Now in <head> section
.AddTag "link", .BuildAttributes("rel", "stylesheet", "href", "https://cdn.simplecss.org/simple.min.css")
End With ' <head> section closes when it goes out of scope
With po_Helpers.Builders.Html.AddTag("body")
' Now in the <body> section
.AddTag "h1", , "Welcome!" ' Test of a tag with content (3rd parameter)
With .AddTag("div", .BuildAttributes("id", "content")) ' Test of tag with attributes (2nd parameter)
' Test of build a paragraph with content and inline tags (the long way)
With .AddTag("p", , "This is a test of ")
.AddTag "b", , "VBWebAppServer.CBuilderHtml"
.AddContent "."
End With ' When CHtmlTag object goes out of scope, it automatically adds the closing </p> tag to the generate HTML
.AddTag "hr" ' Test of a self-closing tag. It will automatically be added to the generated HTML and no CHtmlTag will be returned
With .AddTag("p", , "Visit the ")
' Link test
.AddTag "a", _
.BuildAttributes("href", "https://www.vbforums.com/showthread.php?893990-VB6-Web-Site-App-Server"), _
"VBWebAppFCGI thread at VBForums"
.AddContent "."
End With
' Test of simplified inline markdown content (faster way to build paragraph content with simple bold/italic/strike/superscript formatting
.AddTag "p", , "You can also add content with //simplified// inline markdown by passing **convert_InlineMarkdown** as the 2^^nd^^ parameter " & _
"of the ~~AddsContents~~ ``AddContent`` method. Test of escaping\**. [[You can even create links with markdown^^]]((https://www.vbforums.com)), " & _
"**so give the link a visit**!", contenttransform_InlineMarkdown
' Test of adding raw HTML content
.AddContent vbNewLine & "<p>You can even add raw HTML. Just make sure you escape it yourself if necessary and pass <i>contenttransform_None</i> to the second parameter of the <code>AddContent</code> method</p>", contenttransform_None
' Report how long it took to build the page
.AddTag "p", , "This page was generated in " & New_C.Timing
End With
End With
' Return the formula and the result as plain text.
po_Response.SendSimpleHtmlResponse po_Helpers.Builders.Html.HtmlString
The above generates the following HTML:
Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>New Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>Welcome!</h1>
<div id="content">
<p>This is a test of <b>VBWebAppServer.CBuilderHtml</b>.</p>
<hr>
<p>Visit the <a href="https://www.vbforums.com/showthread.php?893990-VB6-Web-Site-App-Server">VBWebAppFCGI thread at VBForums</a>.</p>
<p>You can also add content with <i>simplified</i> inline markdown by passing <b>convert_InlineMarkdown</b> as the 2<sup>nd</sup> parameter of the <strike>AddsContents</strike> <code>AddContent</code> method. Test of escaping**. <a href="https://www.vbforums.com">You can even create links with markdown^^</a>, <b>so give the link a visit</b>!</p>
<p>You can even add raw HTML. Just make sure you escape it yourself if necessary and pass <i>contenttransform_None</i> to the second parameter of the <code>AddContent</code> method</p><p>This page was generated in 0.67msec</p>
</div>
</body>
</html>
Which looks like this in the browser:
Attachment 183598
PLEASE NOTE: This is very new code, and is very lightly tested. Bugs are all but guaranteed. Please let me know if you find any and I will fix them. Also, the programming interface may change significantly as I use it more and discover shortcomings, so don't make anything serious that relies on this new feature (or any part of VBWebAppServer for that manner) yet!
Notes on VBWebAppServer's Simplified Inline Markdown
I'm using my own flavour of "markdown" (I know, I know - just what the world needs). It has just a few tags chosen to make it easier to do inline formatting of text content in HTML documents. For example, if you want bold or italic spans in a paragraph. This feature has also been lightly tested, so beware of bugs.
Consider this markdown string:
Code:
"You can also add content with //simplified// inline markdown by passing **convert_InlineMarkdown** as the 2^^nd^^ parameter of the ~~AddsContents~~ ``AddContent`` method. Test of escaping\**. [[You can even create links with markdown^^]]((https://www.vbforums.com)), **so give the link a visit**!"
It will be transformed to the following HTML:
Code:
You can also add content with <i>simplified</i> inline markdown by passing <b>convert_InlineMarkdown</b> as the 2<sup>nd</sup> parameter of the <strike>AddsContents</strike> <code>AddContent</code> method. Test of escaping**. <a href="https://www.vbforums.com">You can even create links with markdown^^</a>, <b>so give the link a visit</b>!
Here are the markdown tags and their respective HTML translations:
Code:
** -> Bold, e.g. <b></b>
// -> Italic, e.g. <i></i>
__ -> Underline, e.g. <u></u>
^^ -> Superscript, e.g. <sup></sup>
~~ -> Strikethrough, e.g. <strike></strike>
`` -> Code, e.g. <code></code>
[[LinkText]]((LinkTarget)) -> Hyperlink. e.g. <a href="LinkTarget">LinkText</a>
Enjoy!
-
Re: VB6 Web Site/App Server
Updated the source in post one, and made some small changes to the CBuilderHtml demo code to show how you can add stuff to the <head> section. Also added some more comments to make it easier to understand what's happening when building an HTML page with the CBuilderHtml class.
-
Re: VB6 Web Site/App Server
Sorry folks, I managed to muck up the last update. It's fixed now in the latest post, so if you had any trouble with yesterday's update, the latest version should be fine.
-
1 Attachment(s)
Re: VB6 Web Site/App Server
Another fun update, demonstrating how you might dynamically generate a QR code JPEG and serve it to the browser.
In the demo app, you can navigate to http://127.0.0.1:8080/qrencode/texttoencode, and a QR code image will appear in your browser. For example, here's what you see if you navigate to http://127.0.0.1:8080/qrencode/https://www.vbforums.com:
Attachment 183609
This is generated using the following code in the demo CApp class:
Code:
ElseIf po_Helpers.Regex.Test(po_Req.Url(urlsection_Path), "^qrencode/", False) Then
' Generate a QR Code image and send it back to the client as a JPEG
Dim l_QrData As String
Dim lo_QrEncode As cQREncode
Dim lo_QrImage As cCairoSurface
Dim la_QrImage() As Byte
Dim l_QrWidth As Long
Dim l_QrHeight As Long
' The portion of the requested path after "qrencode/" is the text that the client wants to encode
l_QrData = Mid$(po_Req.Url(urlsection_Path), Len("qrcode/") + 1)
Set lo_QrEncode = librc6QrEncode
If lo_QrEncode Is Nothing Then
' Uhoh! RC6Widgets.dll not found!
po_Response.SendSimplePlainTextResponse "To use the QR code feature, you must first copy RC6Widgets.dll to " & pathSystem, , 500
Else
' Encode the passed text to a QR Code image surface
Set lo_QrImage = lo_QrEncode.QREncode(StrConv(l_QrData, vbFromUnicode), , , 10)
' Add a white border around the QR code
With lo_QrImage
l_QrWidth = .Width + 20
l_QrHeight = .Height + 20
End With
Set lo_QrImage = lo_QrImage.CropSurface(-10, -10, l_QrWidth, l_QrHeight)
With lo_QrImage.CreateContext
.Rectangle 0, 0, l_QrWidth, l_QrHeight
.Rectangle 10, 10, l_QrWidth - 20, l_QrHeight - 20
.SetSourceColor vbWhite
.FillRule = CAIRO_FILL_RULE_EVEN_ODD
.Fill
End With
' Send the QR Code JPEG to the browser
lo_QrImage.WriteContentToJpgByteArray la_QrImage
po_Response.SendSimpleByteArrayResponse la_QrImage, , , "image/jpeg"
End If
Enjoy! :)
-
Re: VB6 Web Site/App Server
-
Re: VB6 Web Site/App Server
Good project, but would it be possible to do without RC6?
-
Re: VB6 Web Site/App Server
G'Day GB
Quote:
Originally Posted by
germano.barbosa
Good project
100% agree :)
Quote:
Originally Posted by
germano.barbosa
would it be possible to do without RC6?
Why don't you want to use RC6 ?
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
germano.barbosa
Good project, but would it be possible to do without RC6?
Thank you. Yes it would be possible, but a fair amount of work for little (if any) benefit IMHO. You would need to make the following replacements:
- SQLite
Use ADO and Jet instead (in many cases slower)
- cArrayList
Use the vanilla VB6 arrays (maybe better performing, but more painful for things like adding/removing elements)
- cWebServer
Roll your own using winsock API or Winsock control.
- cWebResponse/cWebRequest
Roll your own HTTP header and body parser, and WebSocket stuff (if you want to support WebSockets).
- cSortedDictionary
Use Scripting.Dictionary (slower)
- cStringBuilder
Roll your own or use one found in the codebank. Or just use vanilla VB6 string building (slower)
- cCollection
Use the vanilla VB6 Collection (slower, and without convenience methods like "Exists")
- cFSO
Use Scripting.FileSystemObject (slower)
- cCrypt
Roll your own/Use APIs for: URLEncode/URLDecode, SHA256, Cryptographic random number generation, String to UTF8 conversion.
- Cairo
Roll your own QR Encoding (or find something on the Internet). This one is optional, it was just for the demo app.
There are somewhere around 200 lines of code that use RC6 in this project. At a 10x estimate, you would need to write about 2000 lines of code to replace RC6. That's a conservative estimate, I wouldn't be surprised if you need to write more.
But the source is there if you want to fork it. I know some people don't want to use RC6, so they might appreciate your efforts!
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
Thank you. Yes it would be possible, but a fair amount of work for little (if any) benefit IMHO. You would need to make the following replacements:
- SQLite
Use ADO instead (in many cases slower)
- cArrayList
Use the vanilla VB6 arrays (maybe better performing, but more painful for things like adding/removing elements)
- cWebServer
Roll your own using winsock API or Winsock control.
- cWebResponse/cWebRequest
Roll your own HTTP header and body parser, and WebSocket stuff (if you want to support WebSockets).
- cSortedDictionary
Use Scripting.Dictionary (slower)
- cStringBuilder
Roll your own or use one found in the codebank. Or just use vanilla VB6 string building (slower)
- cCollection
Use the vanilla VB6 Collection (slower, and without convenience methods like "Exists")
- cFSO
Use Scripting.FileSystemObject (slower)
- cCrypt
Roll your own/Use APIs for: URLEncode/URLDecode, SHA256, Cryptographic random number generation, String to UTF8 conversion.
- Cairo
Roll your own QR Encoding (or find something on the Internet). This one is optional, it was just for the demo app.
There are somewhere around 200 lines of code that use RC6 in this project. At a 10x estimate, you would need to write about 2000 lines of code to replace RC6. That's a conservative estimate, I wouldn't be surprised if you need to write more.
But the source is there if you want to fork it. I know some people don't want to use RC6, so they might appreciate your efforts!
That's a lot of work and you know I'm not a fan of re-inventing the wheel. I'd recommend that he doesn't try to re-create all this unless he wants to for the challenge of it but there is absolutely no value in reproducing sub-standard versions of something someone already created.
-
Re: VB6 Web Site/App Server
The biggest problem for me is that RC6 is not opensource, I use it for other projects, but the least, if it was opensource I wouldn't worry
-
Re: VB6 Web Site/App Server
Yea, I get it. It's not future-proof while it's survival depends on a single individual. That may change one day perhaps.
-
Re: VB6 Web Site/App Server
If you use multiple commercial controls, which are not open source and are not maintained anymore.
Are they future proof? As long as the OS and development platform supports them.
Is open source future proof? No for same reasons.
I really don't see the drive for having everything open source.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
Arnoutdv
If you use multiple commercial controls, which are not open source and are not maintained anymore.
Are they future proof? As long as the OS and development platform supports them.
Is open source future proof? No for same reasons.
I really don't see the drive for having everything open source.
Let me highlight the important part:-
Quote:
Yea, I get it. It's not future-proof while it's survival depends on a single individual. That may change one day perhaps.
That changes everything. If Bill Gates kicks the bucket tomorrow, there will still be plenty of people at Microsoft who can make sure VB6 runs on Windows 13. God forbit it, but if Olaf shuffles off his mortal coil, then RC6 is just dead. Who will fix it when it crashes applications on Windows 13 or Windows 26?
-
Re: VB6 Web Site/App Server
And if a product is abandoned then the future is also not clear.
See the multiple threads about commercial components which are not maintained/updated anymore.
Especially for freeware, enjoy it as long as it works.
If at some point it doesn't work anymore on a newer platform I think your "own" product will have more problems then just the single non open source component.
Bet lets agree to disagree.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
Arnoutdv
And if a product is abandoned then the future is also not clear.
See the multiple threads about commercial components which are not maintained/updated anymore.
Especially for freeware, enjoy it as long as it works.
If at some point it doesn't work anymore on a newer platform I think your "own" product will have more problems then just the single non open source component.
Bet lets agree to disagree.
I can still play the original Prince of Persia on DOSBox so I guess there's that possibility of unnatural longevity with zero developer input. ;)
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
Arnoutdv
If you use multiple commercial controls, which are not open source and are not maintained anymore.
Are they future proof? As long as the OS and development platform supports them.
Is open source future proof? No for same reasons.
I really don't see the drive for having everything open source.
I use 99% open source, not a third party control, only mine or available here on the forum
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
germano.barbosa
I use 99% open source...
Well, that's only (mostly) true when you run your VB6-IDE on Linux+Wine -
and when your customers run your App on Linux as well...
If you develop on Windows (and your compiled App runs on Windows), then you're depending on about 90% closed source -
(the OS-kernel, the OS-specific drivers, and all the libs in SysWow). ;)
Olaf
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
Can you post the HTML source for that page? I will show you what to put on the server side.
sorry for late response
this is my html example
Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<title>Aligning Buttons</title>
</head>
<body>
<h1 style="color:green;text-align:center;">NumberSender</h1>
<div class="container">
<div class="text-left">
<button type="button">1</button>
<button type="button">2</button>
<button type="button">3</button>
<button type="button">4</button>
<button type="button">5</button>
<button type="button">6</button>
</div>
<table width="500" border="1">
<tr>
<th>ROW #</th>
<th>COLOR #</th>
</tr>
<tr>
<td>ROW 1</td>
<td bgcolor="red">COLOR 2</td>
</tr>
<tr>
<td>ROW 2</td>
<td bgcolor="green">COLOR 5</td>
</tr>
</table>
</body>
<div>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js">
</script>
</body>
</html>
what scenario I'm need:
1) user click any button on the page
2) server receive this number of the button and insert row into table with color
3) user see updated page
-
Re: VB6 Web Site/App Server
Regarding the open/closed source thing, all I'll say is that RC6 (and earlier incarnations) is always the first reference I add to any new project I create. It makes me so much more productive that I am willing to take the risk of Olaf disappearing one day. It's not like it will just suddenly break either, but perhaps eventually an OS update will break it. I suspect that would also mean that VB6 apps will no longer work either, which would mean we even bigger problems to solve.
Anyway, if you don't like the thought of using a closed-source library, that's totally your choice. Like I said, this project is open source and you are more than welcome to fork it if you think there's value in a version without the extra dependency.
-
2 Attachment(s)
Re: VB6 Web Site/App Server
@sergeos
I've modified your HTML a bit to use Jquery for AJAX and modifying the DOM. I'm just familiar with it, so it was easier for me to create the demo. Feel free to substitute your favourite framework or just use vanilla JS if you prefer.
To start, save the following HTML to you web app root folder as "tableaddtest.html":
Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<title>Aligning Buttons</title>
</head>
<body>
<h1 style="color:green;text-align:center;">NumberSender</h1>
<div class="container">
<div id='buttons' class="text-left">
<button type="button">1</button>
<button type="button">2</button>
<button type="button">3</button>
<button type="button">4</button>
<button type="button">5</button>
<button type="button">6</button>
</div>
<table id='mytable' width="500" border="1">
<tr>
<th>ROW #</th>
<th>COLOR #</th>
</tr>
<tr>
<td>ROW 1</td>
<td bgcolor="red">COLOR 2</td>
</tr>
<tr>
<td>ROW 2</td>
<td bgcolor="green">COLOR 5</td>
</tr>
</table>
</div>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script>
// Hook each # button's click event.
$('#buttons button').click(function() {
// # button clicked
var number = $(this).text();
// Send AJAX query to the server at /numberreceiver/<number>
$.ajax({
url: "/numberreceiver/" + number,
})
.done(function( json ) {
// Add a row to the table using the JSON response from the server
json = $.parseJSON(json);
var markup = "<tr><td>ROW " + ($('#mytable tr').length) + "</td><td bgcolor=" + json.bgcolor + ">COLOR " + number + "</td><</tr>";
$("#mytable").append(markup);
if ( json.status != 200 ) { alert('Error #' + json.status + ': ' + json.errormessage); }
});
});
</script>
</body>
</html>
Then add the following code to the CApp class (somewhere after the If po_Helpers.Regex.Test(po_Req.Url(urlsection_Path), "^showcase/[0-9]+$", False) Then showcase code section:
Code:
ElseIf po_Helpers.Regex.Test(po_Req.Url(urlsection_Path), "^numberreceiver/[0-9]+$", False) Then
' Build JSON response
' JSON helper methods are forthcoming,
' but for now we'll have to use the ComplexResponse and manually add an "Content-Type: application/json" header
With po_Response.ComplexResponse
.AddHeaderEntry "Content-Type", "application/json"
Set lo_Json = New_C.JSONObject
With lo_Json
.Prop("status") = 200
' Get the color index # from the end of the URL path
.Prop("number") = Split(po_Req.Url(urlsection_Path), "/")(1)
Select Case .Prop("number")
Case 1
.Prop("bgcolor") = "purple"
Case 2
.Prop("bgcolor") = "red"
Case 3
.Prop("bgcolor") = "blue"
Case 4
.Prop("bgcolor") = "yellow"
Case 5
.Prop("bgcolor") = "green"
Case Else
' Uhoh! Unknown color index
.Prop("status") = 500
.Prop("errormessage") = "Unknown color index #" & .Prop("number")
.Prop("bgcolor") = "gray"
End Select
End With
.SetResponseDataBytes lo_Json.SerializeToJSONUTF8
End With
Finally, start the app server and navigate to http://127.0.0.1:8080/tableaddtest.html and try clicking some buttons. You should see something like this:
Attachment 183696
Until you click #6, then you will see a simulated error:
Attachment 183697
I hope the code and comments are enough to demonstrate how this type of thing can be done, but let me know if you have any questions.
-
Re: VB6 Web Site/App Server
-
Re: VB6 Web Site/App Server
Are you having a problem using this with IPv6?
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
jpbro
Are you having a problem using this with IPv6?
is it like this?
VbWebApp.exe /spawn 1 /ip 240e:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:6f30 /port 80
it returns this:
***ERROR: -2147221504 Couldn't start Listener on 127.0.0.1:80
ERROR: -2147221504 Could not start app server.
***ERROR: -2147221504 Couldn't start Listener on 127.0.0.1:80
ERROR: -2147221504 Could not start app server.
……………………………………
-
Re: VB6 Web Site/App Server
mind blowing effort!! but need documentation to create complex templates very few examples.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
silver-surfer
mind blowing effort!! but need documentation to create complex templates very few examples.
This was/is a work in progress so unfortunately there is no documentation at this point. Can you provide more details about what are you hoping to create?
-
Re: VB6 Web Site/App Server
-
Re: VB6 Web Site/App Server
Marry Christmas
it is like php/aspx pages i have to add 3rd party js libraries like ui elements , gauges , charts and many more
-
Re: VB6 Web Site/App Server
How to make a simple web design tool with VB6? Or turn a normal VB control into a web page. The ultimate goal is to achieve cross-platform.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
silver-surfer
Marry Christmas
A belated Merry Christmas to you :)
Quote:
Originally Posted by
silver-surfer
it is like php/aspx pages i have to add 3rd party js libraries like ui elements , gauges , charts and many more
Yes, anything running on the browser side will need its own browser-native code (JS) and UI elements. Things like gauges and charts could be rendered server side using Cairo or GDI+ though and you could send the PNGs/JPEGs/SVGs to the browser as needed. NOTE: SVGs generation would be done through Cairo only, not GDI+ AFAIK.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
xiaoyao
How to make a simple web design tool with VB6? Or turn a normal VB control into a web page. The ultimate goal is to achieve cross-platform.
Don't think it's very feasible, but even if do-able it would be an extraordinary amount of work. Best you could hope for is an existing well-separated back-end/front-end VB6 code base, and then you only need to re-write the front-end UI for the web/browsers and get to keep all your back-end VB6 code. In my case I have about a 70/30 back-end/front-end split, so it means only rewriting the 30% front-end for the web and some glue code to convert browser requests into VB6 method calls and reply with JSON results to the browser.
-
Re: VB6 Web Site/App Server
-
Re: VB6 Web Site/App Server
It is said that API can automatically help you create websites as long as you speak.
So there's no need to design the interface anymore, it's possible.
-
Re: VB6 Web Site/App Server
Quote:
Originally Posted by
xiaoyao
It is said that API can automatically help you create websites as long as you speak.
So there's no need to design the interface anymore, it's possible.
Not sure what you're trying to say here. Yes, you can develop an API for your backend server, but it doesn't automatically help you do anything. You will still need an front-end interface unless you want to send raw API requests with Curl or something and manually parse the responses yourself (which I guess is still an interface of sorts).