We are still running on v. 12 and 14.1 (two separate solutions), while waiting for help to upgrade the 12 to 14.2. The upgrade has so far taken almost a month.
So I had to dive back into WAM’s in 12 and added a <svg> element.
Which is then promptly messed up by Lansa, moving the SVG contents out of the element and making the <svg> element empty. Just like I experienced with 14.1.
I made this error and spent a long time trying to spot it:
Select_Sql Fields((#ANTAL 'SUM(ANTAL')) From_Files(TRANS) Where(...)
That is how I learned that the optional SQL source for a field is not validated in the editor or during compilation. Adding the missing end-parenthesis fixed my error:
Select_Sql Fields((#ANTAL 'SUM(ANTAL)')) From_Files(TRANS) Where(...)
Working with CONDCHECK I got confused. The condition check works to mark a field that is filled out incorrectly, but the condition is to be read as “these conditions should be satisfied, if not…”.
Which makes sense; you write the condition that you want satisfied. If it isn’t you get the message.
My problem was that I thought of it in the context of if … then; if this condition is satisfied, I should get the message. Which I now realise was wrong.
I needed this, so here it is for posterity:
In the list BUTLST, I wanted to select the value from the field WCHAR36, on the entry where the value from the field BUTNR matched the mapped field IZBUTNR.
So, in sequence, I wanted
the list BUTLST
the value from the field WCHAR36
on the entry where the value from the field BUTNR
... lxml:list-entries/lxml:entry/lxml:column[@name='BUTNR'][text() ... ]
matched the mapped field IZBUTNR
... = key('field-value', 'IZBUTNR') ...
Completed that is
/lxml:data/lxml:lists/lxml:list[@name='BUTLST']/lxml:list-entries/lxml:entry/lxml:column[@name='BUTNR'][text() = key('field-value', 'IZBUTNR')]/../lxml:column[@name='WCHAR36']
Def_List Name(#BUTLST) Fields(#BUTNR #BUNAVN #WCHAR36) Type(*WORKING) Entrys(*MAX)
Web_Map For(*BOTH) Fields(#IZBUTNR #BUTLST )
I keep forgetting this, cause I do development in other languages and frameworks as well, and nothing in the LANSA editor stops me. But WAM command handlers must not have a name of more than 8 characters.
Or rather, it can and it will work, but then when you try to set it up in the VLF, you, again without warning, enter the more-than-8 character name and lo and behold, you end up with errors on your site.
Instead, a command handler named, for example, CH_FAKKOP, should be referenced in the VLF by the first 8 characters, CH_FAKKO, even though the WAM component is 9 characters.
Edit: This also applies to the WAM name in XSLT, like
<xsl:with-param name="on_change_wrname" select="'UHandleEvent'" />
<xsl:with-param name="on_change_wamname" select="'CH_FAKKO'" />
This is one of those issues that arise from me coming from a different background than what I imagine a typical Lansa developer, indeed a typical i series developer, come from. It is a useful reminder what decimals actually mean.
For example, I have a repository field that is defined like this:
Define Field(#JSN) Type(*SIGNED) Length(4) Decimals(2)
That means, a signed decimal value with 2 digits before the decimal point and 2 digits after the decimal point. In a function, I calculate the value and exchange it back to application calling. In that application, I (unfortunately) have an override, changing the number of decimals.
Override Field(#JSN) Decimals(1)
This was probably done to format the display of the value but where I imagined the value would be passed in a lower level format and then parsed in relation to the definition, this is not what happens.
Instead, the value is still the same 4 digits, but one of those that was after the decimal point is now before the decimal point. The value has been multiplied by 10^1; a value of 0.21 is now 2.1.
Because the override only moved the decimal point.
As someone mentioned a while back on the forum, getting a newline, or indeed any character from a character code, is difficult to find. But it is easy, once you know how:
returns a carriage return in ANSI. I’d probably prefer
(13).AsUnicodeString + (10).AsUnicodeString
as I am primarily targeting the Windows platform.
However, this is a solution for Lansa v. 14, not v. 12, where AsUnicodeString does not exist. In Lansa v. 12 you write
(13).AsByte.AsString + (10).AsByte.AsString
A quick follow-up on .IsValidPassword: The highest entropy of a password that would be accepted by .IsValidPassword(strong) can be calculated like this:
1 upper - 26 characters
1 lower - 26 characters
1 numeric - 10 characters
1 special - 7 characters
4 remaining - 26+26+10+7+1(space) = 70 characters
log2(26+26+10+7)*4+log2(26)*2+log2(10)+log2(7) ~~ 40 bits of entropy
If the requirement was simply 8 characters, the entropy could be
log2(70)*8 ~~ 49 bits of entropy
Entropy is used to calculate how long it would take to crack a password, provided it wasn’t an already know password:
Number of guesses = 2^(entropy - 1)
If we can make 1,500 guesses per second, divide by (1500 * 86400) (86400 is the number of seconds per day):
40 bits of entropy ~ 4,000 days
49 bits of entropy ~ 2.1 million days
What about words? Using words doesn’t necessary increase entropy, as words are part of a finite dictionary. The complete dictionary is somewhere between 100,000 and 200,000 but most people only use 3,000 words.
log2(3000)*4 ~~ 46 bits of entropy ~ 271,000 days
log2(3000)*5 ~~ 58 bits of entropy ~ 1.1 billion days
Using 4 words from your own dictionary would give a stronger password than what .IsValidPassword(strong) accepts, even if those 4 words would not get accepted by that method.
I am not impressed with the Lansa v. 14 SP2 addition of .IsValidPassword (see documentation):
I am sorry. This is completely insufficient and wrong. Also, this is no secret as everyone knows that these rules are insufficient and wrong. Or should know.
So, what are the right rules?
- Long passwords – this equals greater entropy
- Use words that can be remembered – this way the password doesn’t have to be written down or stored digitally
- Do not require use of mixed case and/or special characters – as this lowers entropy
A follow-up to this post, please note that strings can only take up to 65535 bytes at a time. However, #RESPONSE.ContentString appears to accept longer strings. The former is a problem, the latter is a feature.
This works, provided #TEMP_OUTPUT is never truncated:
#RESPONSE.ContentString += #TEMP_OUTPUT