It's meant to be an Advanced Business Language

Posted by jmls on 29-Mar-2013 03:26

It would be nice, seeing as we're all getting into rest and web and mobile stuff, for the language to make url stuff easier. **

For example:

Base64-encode

converts a memptr / raw into a string. Problem is that string can contain characters like +, = and / which can't be used in a url

Why isn't there a Base64-[en|de]codeURL() function ??

I need to be able to generate base64-encoded safe url values outside webspeed, and am going to have to manually replace + with "-", = with "." and / with "_" every time I encode / decode.

what a pita.

** if there is such a function, then please consider this post to be the ranting of an old, deluded man ...

All Replies

Posted by gus on 29-Mar-2013 11:00

base64 encoding is what it is, not what you want it to be.

isn't url encoding what you actually need?  iow, where a / is encoded as %2f, + as %2b, and so on?

but you are right that the 4gl should have an inbuilt solution to the problem and currently it doesn't.

Posted by jmls on 29-Mar-2013 12:18

>> base64 encoding is what it is, not what you want it to be

well, kinda

RFC 4648 Base-N Encodings October 2006

5. Base 64 Encoding with URL and Filename Safe Alphabet

Other languages like python have also come across this "problem" and

implemented language features to help.

url encoding is ok, except it's not available outside webspeed

Posted by Peter Judge on 29-Mar-2013 12:28

url encoding is ok, except it's not available outside webspeed

>

I guess. But WebSpeed is ABL and is shipped in $DLC/src. There's a url-encode function in cgiutils.i in $DLC/src/web/method which you would be able to use.

It may not be a built-in object, but it exists and works with ABL. Yes, it's an include, but that's the way the cookie crumbles

-- peter

Posted by jmls on 29-Mar-2013 12:53

 * jmls has a heart attack.

"Include file" ??

nice pun regarding the cookies. But I'm not using any

I'm also sure that we can write a base64-encode/decode using the 4GL

(cough) as well. However, someone @ psc obviously needed a faster

version ...

Posted by Thomas Mercer-Hursh on 29-Mar-2013 15:50

One issue I can see here is that "URL Encoding" as a concept is not specifically defined in the same way that base 64 encoding is.  For your purposes, base 64 with a few twists would be acceptable, but for others, something different might be preferable, e.g., something not case sensitive.  So, it seems to me that this is the perfect sort of thing to put in a service object and code the way you want it.  You aren't doing them thousands to the second, are you?

It seems to me that one of the unfortunate decisions in the history of ABL was the decision to incorporate every new behavior as a new keyword.  If, instead, we had gone OO with V7 and put all this stuff into class libraries, even class libraries written in C, which were still overridable, the language would be far, far cleaner today.

Posted by jmls on 29-Mar-2013 15:58

not quite - there are only three characters in base64-encoding that

are not url-safe

+

/

=

so, if these chars were not present, there would be no need to url-encode at all

in fact, all I have done is to replace

+ with -

/ with _

and = with .

the - _ and . are not part of the base-64 encoding charset, so the

resultant "replaced" base64 encoding is urlsafe by default

On 29 March 2013 20:50, Thomas Mercer-Hursh

Posted by Thomas Mercer-Hursh on 29-Mar-2013 16:11

So, for you, doing a base 64 encode and a couple of replaces will get the job done.  My point is that this particular solution is idiosyncratic and someone else might well want something else.  It is possible and appropriate to implement a base 64 encode function in the language, if one doesn't mind the keyword bloat, because base 64 encoding is a well defined standard.  URL encoding is not.

Posted by Peter Judge on 01-Apr-2013 07:58

One issue I can see here is that "URL Encoding" as a concept is not

specifically defined in the same way that base 64 encoding is. For your

Section 2.2 of RFC 1738 contains information about URL encoding. https://www.ietf.org/rfc/rfc1738.txt

-- peter

Posted by Thomas Mercer-Hursh on 01-Apr-2013 09:16

Yes, but that is specifying only what the universe of legal expressions is, not how to encode some source string into a string to use.

Posted by gus on 02-Apr-2013 10:10

It seems abundantly clear to me. It says:

"octets may be encoded by a character triplet consisting of the character "%" followed by the two hexadecimal digits (from "0123456789ABCDEF") which forming the hexadecimal value of the octet. (The characters "abcdef" may also be used in hexadecimal encodings.)

Octets must be encoded if they have no corresponding graphic character within the US-ASCII coded character set, if the use of the corresponding character is unsafe, or if the corresponding character is reserved for some other interpretation within the particular URL scheme."

and

"All unsafe characters must always be encoded within a URL. For example, the character "#" must be encoded within URLs even in systems that do not normally deal with fragment or anchor identifiers, so that if the URL is copied into another system that does use them, it will not be necessary to change the URL encoding."

and a lot of other things, including a list of unsafe characters. What else do you need to know?

Posted by Thomas Mercer-Hursh on 02-Apr-2013 10:35

Could be we are talking at cross purposes here.  Clearly, Julian has to either remove, replace, or convert the non-legal characters in the base 64 string in order to use it in an URL.  There isn't anything unclear about that.

My question goes back to why Julian is starting with base-64-encode in the first place.  That he is using that suggests that he has some starting source string which either has its own legal character issues or for some reason he doesn't want to put it out there in plain text, e.g., because it contains information which should not be public or because, if he did, unauthorized people could guess at the address for someone else's data.

My point is that:

1. Converting a string to base 64 encode is a well-defined operation on which there is shared agreement what the algorithm and results should be.

2. Converting a string to a URL form is not well-defined and can be done in a great many ways depending on one's needs and purposes.  E.g., a module on my Drupal website strips out common words from the title of the page and glues together the remaining words with - to create a semi-mnemonic URL.  It happens that whatever Julian's needs are, base-64-encode gets close to something usable, except for this problem with a few characters.  But, that it does get close is really somewhat accidental.   There are many ways that one could mangle a source string to produce a valid URL with varying levels of obscurity, arbitrariness, or whatever the criteria are in a particular instance.

Therefore, it makes sense for there to be a standard method to produce a base-64-encode, but it doesn't really make any sense for there to be a standard string to URL function that is a part of the language.  It makes perfect sense for anyone who needs such a thing to code a utility to do whatever they want, but not a standard one that applies to everyone.  E.g., something similar to base-64 would actually be a negative feature in the Drupal context since a mere node number would be sufficient in the absence of the more intuitive name.

Posted by jmls on 02-Apr-2013 11:33

I need to generate a token for session management, which is

guid-based. This token must be passed either as part of a url or form

data.

I do not want to send the guid itself, as that is a security risk. So,

I encrypt the guid, which gives me a raw/memptr. I then have to

base64-encode the raw value in order to make it a "string".

What I was originally saying was that this base64-encoding is 99.9%

url safe already, and it's a shame that there isn't an option on the

function to make it url safe.

This is a common problem in the web world, and several languages

(python etc) accept that there is a requirement, and have provided

functions to do this as part of the language.

Yes, I have created a class and method that does this for me. It's a

shame that it's not part of the language because people will be

re-inventing this particular wheel time and time again over the next

few years

And, as I have already pointed out somewhere in this thread, there is

a RFC for this. So it's not just me

On 2 April 2013 16:35, Thomas Mercer-Hursh

Posted by Admin on 02-Apr-2013 11:58

If you´d be sharing your class, the rest fo the world wouldn´t need to reinvent.

But I´m with you, that OpenEdge out of the box should not stand behind those webbie languages when it comes to productivity. We should be able to focus on business issues, not on technical issues like url encoding.

So making the WebSpeed API´s easy to use (and documented) outside of WebSpeed should be an easy catch for OpenEdge.

And while we´re talking about it, the ADM2 query manipulation is also a hidden gem burried in the rest of the ADM2.

Posted by Thomas Mercer-Hursh on 02-Apr-2013 12:16

Isn't the Webspeed equivalent just an include file?

Posted by jmls on 02-Apr-2013 12:48

I'll make it available

Posted by jmls on 02-Apr-2013 12:48

no, that urlencodes the whole string again It's much more efficient

to just replace 3 chars than to check for all the url encodings.

And then you don't have to use include files ...

On 2 April 2013 18:16, Thomas Mercer-Hursh

Posted by Admin on 02-Apr-2013 13:03

While he still leaves it a mystery once more what's so bad about include files

Posted by gus on 02-Apr-2013 13:03

And, as I said in the beginning, I agree the language should have this.

Posted by jmls on 02-Apr-2013 14:03

Well, let "him" explain:

I think that in the wrong hands, include files lead to terrible

coding. Ever had to debug several levels of include files, with each

level adding options ? It's a pure maintenance and debugging

nightmare. {&*} is a powerful option for includes - but with great

power comes great responsibility , and too few people exercise that

responsibility.

Mike, however, is one of those people.

With the advent of oo in 10.2B and above, there is very very little

reason to use include files for any new project / coding.

There are a couple of areas where you and I can actually agree that

they are still needed - but only because of deficiencies in the 4GL.

A couple of these areas are

#1) temp-table definitions.

#2) Enums

I can't think of many more areas where an include file would be better

than a properly designed class

Posted by Thomas Mercer-Hursh on 02-Apr-2013 14:30

My point was not to reignite the include file holy war ... which clearly should be a separate thread, if anything ... but to wonder if it being an include file meant that it was just some more ABL code ... i.e., no different in the end from what Julian has done, and done perhaps more efficiently.

And, since you seem to be fond of include files as language extensions, why not just apply that principle here?

Posted by Admin on 02-Apr-2013 14:33

There are a few other areas where Include files come very, very handy.

Especially as long as this 4GL language provides no way to return a compile time validated reference to a class.

oService = CAST (ServiceContainer:GetService (Progress.Lang.Class:GetClass ("Consultingwerk.Framework.ISomeService")), Consultingwerk.Framework.ISomeService)

requires you to repeat the same type name twice - and hopefully you won't misspell the one in quotes... otherwise hell breaks loose.

Put this in an include file, with the service type name as a parameter and the CAST (where the type name is validated at compile time) will also ensure that the service type name passed to the Class:GetClass() in quotes is correct.

oService = {get-service.i Consultingwerk.Framework.ISomeService}.

We've written a few other include files that help overcome the limitations of the OO-ABL support, like for iterating object sets etc.

I'm saying that a hand full (o.k. two hands full) of carefully crafted include files make the whole code easier to read and understand. Hence my allergy to banning include files in general. And in the context of a framework they become part of the language.

Of course, I've seen those nightmare include file scenarios as well. So I can understand what Julian is saying.

Posted by Admin on 02-Apr-2013 14:41

And, since you seem to be fond of include files as language extensions, why not just apply that principle here?

First I also wrote that I don't want to use more than two hands full of include files (excluding temp-table defs).

Second, I assume that you haven't looked at the WebSpeed API's recently. Those incude files define functions prototypes and the implementations are in a super procedure referenced by a SHARED or GLOBAL-SHARED variable. So anybody attemting to use them outside of WebSpeed in OO code will have to do extra work first.

Wouldn't it be more straight forward if the developer of the tool also migrates such API's to modern code constructs and keeps them accessible for existing WebSpeed code by making the existing functions a wrapper to the functioanlity in the classes?

Posted by Thomas Mercer-Hursh on 02-Apr-2013 14:45

As I said, if we talk about that at all, it should be a different thread.

Posted by Thomas Mercer-Hursh on 02-Apr-2013 14:56

The requirement here seems to me to be one that is handled adequately by doing exactly as Julian has done.

Given the commitment to "complete" the OOABL that we have heard from PSC at the Partner+ conference, how about including a good language extension mechanism in that so that we don't keep multiplying the keywords?

Posted by Admin on 02-Apr-2013 15:03

Nobody wants new keywords. And Progress has left the path of adding new keywords/statements a while ago. Just look at all the new Progress.* classes.

Posted by jmls on 13-Apr-2013 13:44

here's the (very) simple code to make a base64 encoded string url safe (ie it can be passed as a url parameter)

  /** make base64 string url safe

    * @param base64-encoded string

    * @return url safe base64-encoded string

    */ 

  method private longchar Base64URLEncode(p_data as longchar):

    def var lv_Data as longchar no-undo.

    assign lv_data = p_data

           lv_Data = replace(lv_data,"+","-")

           lv_Data = replace(lv_data,"/","_")

           lv_Data = replace(lv_data,"=",".").

    return lv_Data.          

  end method.

  /** convert url safe base64 string into standard base64

    * @param url safe base64-encoded string

    * @return base64-encoded string

    */ 

  method private longchar Base64URLDecode(p_data as longchar):

    def var lv_Data as longchar no-undo.

    assign lv_data = p_data

           lv_Data = replace(lv_data,"-","+")

           lv_Data = replace(lv_data,"_","/")

           lv_Data = replace(lv_data,".","=").

    return lv_Data.          

  end method.

use it thus:

encode:

x = Base64URLEncode(base64-encode(encrypt("somestring",EncryptKey))).

decode:

y = string(decrypt(base64-decode(Base64URLDecode(x)),EncryptKey))

Posted by jmls on 13-Apr-2013 13:44

so, 11.3 then

This thread is closed