Why Language Key is displayed like 1 character instead of 2? - abap

I was trying to learn how to use String Templates and encountering displaying characters.
What I was trying to display is:
SAP Logon Language Key EN
using this line of code:
WRITE: |{ text-003 } { sy-langu }|.
But instead, it only displays:
SAP Logon Language Key E
it only displays the first character of the language instead of the full 2 letters which are EN

SAP language codes are displayed as two letters, but are internally stored as just one. There are various data-types where the internal and the external representation differ. It's called a conversion-routine and it's defined on the level of the domain in the ABAP dictionary.
If you want to convert to the external representation of a language field, use the function module CONVERSION_EXIT_ISOLA_OUTPUT. If you want to do the reverse - convert a UI representation to the database representation - use CONVERSION_EXIT_ISOLA_INPUT.

To complete Philipp answer, you may also use WRITE to convert from database to external representation, it will automatically search the right conversion routine (ISOLA when it's about SY-LANGU):
DATA display_language_code TYPE c LENGTH 2.
WRITE sy-langu TO display_language_code.
ASSERT display_language_code = 'EN'.

Related

regular expression, how to replace a part of a text preserving its length

I have, in a database, records that are serialized PHP strings that I must obfuscate emails if there are any. The simplest record is like {s:20:"pika.chu#pokemon.com"}. It is basically saying: this is a string of length 20 which is pika.chu#pokemon.com. This field can be kilobytes long with lot of emails (or none) and sometimes it is empty.
I wish I could use a SQL regular expression function to obfuscate the user part of the email while preserving the length of the string in order not to break the PHP serialization. The example email above shall be turned into {s:20:"xxxxxxxx#pokemon.com"} where the number of x matches the length of pika.chu.
Any thoughts?
Here is a more complete example of what can be found as serialized PHP:
a:4:{s:7:"locales";a:3:{i:0;s:5:"fr_FR";i:1;s:5:"de_DE";i:2;s:5:"en_US";}s:9:"publisher";s:18:"john#something.com";s:7:"authors";a:2:{i:0;s:21:"william#something.com";i:1;s:19:"debbie#software.org";}s:12:"published_at";O:8:"DateTime":3:{s:4:"date";s:26:"2022-01-26 13:05:26.531289";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}}
I tried to do it using native functions but it not worked because functions like REGEXP_REPLACE don't let you manipulate the match to get the size of it, for example.
Instead, I've created a UDF to do that:
CREATE TEMP FUNCTION hideEmail(str STRING)
RETURNS STRING
LANGUAGE js AS """
return str
.replace(/([a-zA-Z.0-9_\\+-:]*)#/g, function(txt){return '*'.repeat(txt.length-1)+"#";})
""";
select hideEmail('a:4:{s:7:"locales";a:3:{i:0;s:5:"fr_FR";i:1;s:5:"de_DE";i:2;s:5:"en_US";}s:9:"publisher";s:18:"john#something.com";s:7:"authors";a:2:{i:0;s:21:"william#something.com";i:1;s:19:"debbie#software.org";}s:12:"published_at";O:8:"DateTime":3:{s:4:"date";s:26:"2022-01-26 13:05:26.531289";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}}')
Result:
a:4:{s:7:"locales";a:3:{i:0;s:5:"fr_FR";i:1;s:5:"de_DE";i:2;s:5:"en_US";}s:9:"publisher";s:18:"****#something.com";s:7:"authors";a:2:{i:0;s:21:"*******#something.com";i:1;s:19:"******#software.org";}s:12:"published_at";O:8:"DateTime":3:{s:4:"date";s:26:"2022-01-26 13:05:26.531289";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}}

Get Text Symbol Programmatically With ID

Is there any way of programmatically getting the value of a Text Symbol at runtime?
The scenario is that I have a simple report that calls a function module. I receive an exported parameter in variable LV_MSG of type CHAR1. This indicates a certain status message created in the program, for instance F (Fail), X (Match) or E (Error). I currently use a CASE statement to switch on LV_MSG and fill another variable with a short description of the message. These descriptions are maintained as text symbols that I retrieve at compile time with text-MS# where # is the same as the possible returns of LV_MSG, for instance text-MSX has the value "Exact Match Found".
Now it seems to me that the entire CASE statement is unnecessary as I could just assign to my description variable the value of the text symbol with ID 'MS' + LV_MSG (pseudocode, would use CONCATENATE). Now my issue is how I can find a text symbol based on the String representation of its ID at runtime. Is this even possible?
If it is, my code would look cleaner and I wouldn't have to update my actual code when new messages are added in the function module, as I would simply have to add a new text symbol. But would this approach be any faster or would it in fact degrade the report's performance?
Personally, I would probably define a domain and use the fixed values of the domain to represent the values. This way, you would even get around the string concatenation. You can use the function module DD_DOMVALUE_TEXT_GET to easily access the language-dependent text of a domain value.
To access the text elements of a program, use a function module like READ_TEXT_ELEMENTS.
Be aware that generic programming like this will definitely slow down your program. Whether it would make your code look cleaner is in the eye of the beholder - if the values change rarely, I don't see why a simple CASE statement should be inferior to some generic text access.
Hope I understand you correctly but here goes. This is possible with a little trickery, all the text symbols in a report are defined as variables in the program (with the name text-abc where abc is the text ID). So you can use the following:
data: lt_all_text type standard table of textpool with default key,
lsr_text type ref to textpool.
"Load texts - you will only want to do this once
read textpool sy-repid into lt_all_text language sy-langu.
sort lt_all_Text by entry.
"Find a text, the field KEY is the text ID without TEXT-
read table lt_all_text with key entry = i_wanted_text
reference into lsr_text binary search.
If you want the address you can add:
field-symbols: <l_text> type any.
data l_name type string.
data lr_address type ref to data.
concatenate 'TEXT-' lsr_text->key into l_name.
assign (l_name) to <l_text>.
if sy-subrc = 0.
get reference of <l_text> into lr_address.
endif.
As vwegert pointed out this is probably not the best solution, for error handling rather use message classes or exception objects. This is useful in other cases though so now you know how.

How to add text plus the text written from a Parameter type C in ABAP?

I am working in an ABAP program and I have a question.
For example in C# when we have a String variable: string name; , and we want this to be filled with some data from a textbox but also add some ohter text.
For example:
string name = "Hello: " + textBox1.text;,
And I want to ask you how can I do this in ABAP ??? How to add text plus the text written from a Parameter type C?
CONCATENATE and the concatenate operator && will do it as answered by Jagger and vwegert. To do it with string expressions, you use the below where name is the screen field or whatever that has the name in it (it doesn't need to be a field-symbol):
greeting = |Hello: { <name> }|.
String expressions are extremely useful as they can be used to build up complex values without declaring extra variables - e.g. they can passed as directly as function module or method parameters without first assigning to a local variable.
You can either use the CONCATENATE keyword or -- in newer releases -- string expressions. Be sure to check the online documentation and sample programs available using the transaction ABAPDOCU, it will save you a ton of seemingly basic questions.
The equivalent operator is &&.
So in your case it would be:
name = 'Hello: ' && textBox1->text.

Do the builtin types (c, d, i, f, etc.) have CONVERSION_EXI_* functions? And if so, how to find them?

The WRITE statement has a lot of options, so I was wondering, does it call CONVERSION_EXIT_* functions, or how does it print the primitive data types in so many ways?
And if it does use CONVERSION_EXIT_*s, what are those?
The primitive data types (DATA foo TYPE n LENGTH 10) do not have any conversion exits (ALPHA, etc.) assigned to them.
You can choose them manually, for example with
WRITE ... TO ... USING EDIT MASK '==ALPHA'.
or they can be assigned to a data dictionary domain (transaction code SE11). In this case, they are implicitly called for example:
by the screen (dynpro) processing (unless turned off explicitly).
by WRITE
DATA(langu) = CONV syst-langu( 'E' ). " domain SYLANGU has conv.exit ISOLA
DATA text TYPE c LENGTH 2.
WRITE langu TO text. " conv.exit ISOLA converts 'E' into 'EN'
Except WRITE, ABAP itself does very little to support conversion exits - which is a good thing because the conversion should take place only at the input/output borders of the program and not internally.
It's a good idea to keep all of the data in the internal format as long as you're working on it and only convert it right before the output takes place.

sql injection in integer field

I have an app, and the username field will convert any given value to the integer value using integer.parseint. The app uses JSP and Oracle database.
The URL has been tested with SQLMap and it is not dynamic. So, the only way I can try is via the login form, but I could not bypass it.
When I put ' or 1=1, -- ,the server return error, error for input string.
I want to inject the field, so, how can it be done?
I don't know whether I can use the alternate encoding because it will convert that to integer anyway.
It can't be done.
If the value is parsed as an integer, it can no longer contain any harmful code.