diff --git a/src/00/00/z2ui5_cl_smps_context.clas.abap b/src/00/00/z2ui5_cl_smps_context.clas.abap index b8ae903..84e5de8 100644 --- a/src/00/00/z2ui5_cl_smps_context.clas.abap +++ b/src/00/00/z2ui5_cl_smps_context.clas.abap @@ -1034,33 +1034,53 @@ CLASS z2ui5_cl_smps_context IMPLEMENTATION. METHOD url_param_get_tab. - DATA(lv_search) = replace( val = i_val - sub = `%3D` - with = `=` - occ = 0 ). - - " RFC 3986 allows lowercase hex digits in percent-encodings, so decode - " %3d the same way as %3D (%26 contains no letters and needs no twin) - lv_search = replace( val = lv_search - sub = `%3d` - with = `=` - occ = 0 ). - - lv_search = replace( val = lv_search - sub = `%26` - with = `&` - occ = 0 ). - - lv_search = shift_left( val = lv_search sub = `?` ). - - " prepend & before searching so sap-startup-params is also unwrapped - " when it is the first/only query parameter (typical FLP target mapping) - DATA(lv_search2) = substring_after( val = |&{ lv_search }| sub = `&sap-startup-params=` ). - lv_search = COND #( WHEN lv_search2 IS NOT INITIAL THEN lv_search2 ELSE lv_search ). - - lv_search2 = substring_after( val = lv_search sub = `?` ). - IF lv_search2 IS NOT INITIAL. - lv_search = lv_search2. + " a full URL or a request URI carries a path before its query: cut at + " the FIRST `?` only. A later `?` is a legal, unencoded character of a + " value (`title=why?`) - cutting there dropped every parameter before it + " declared, not inline: DATA( ) from a generic CLIKE parameter is "fixed + " type STRING used for generic type CLIKE" in the extended check + DATA lv_search TYPE string. + lv_search = i_val. + IF lv_search CS `?`. + lv_search = substring_after( val = lv_search sub = `?` ). + ENDIF. + + " The FLP packs the target's own parameters into ONE value, + " sap-startup-params, with its `=` and `&` percent-encoded. Prepend & + " before searching so it is also unwrapped when it is the first/only + " query parameter (typical FLP target mapping). Only THAT value is + " decoded: decoding the whole query first tore every legitimately encoded + " `&` or `=` in any other value apart (`a=x%26y` became a=x and y=), and + " what stands BEFORE the wrapper - sap-client, sap-language - is kept: + " it used to be dropped from every link built from this table + " (abap2UI5's z2ui5_cl_ui5_util_context carries the same fix) + DATA(lv_startup) = substring_after( val = |&{ lv_search }| sub = `&sap-startup-params=` ). + IF lv_startup IS NOT INITIAL. + " lv_before keeps the prepended `&`, so the empty first segment it + " produces below is skipped like a trailing one + DATA(lv_before) = substring_before( val = |&{ lv_search }| sub = `&sap-startup-params=` ). + SPLIT lv_startup AT `&` INTO DATA(lv_packed) DATA(lv_rest). + lv_packed = replace( val = lv_packed + sub = `%3D` + with = `=` + occ = 0 ). + " RFC 3986 allows lowercase hex digits in percent-encodings, so decode + " %3d the same way as %3D (%26 contains no letters and needs no twin) + lv_packed = replace( val = lv_packed + sub = `%3d` + with = `=` + occ = 0 ). + lv_packed = replace( val = lv_packed + sub = `%26` + with = `&` + occ = 0 ). + lv_search = lv_packed. + IF lv_rest IS NOT INITIAL. + lv_search = |{ lv_packed }&{ lv_rest }|. + ENDIF. + IF lv_before IS NOT INITIAL. + lv_search = |{ lv_before }&{ lv_search }|. + ENDIF. ENDIF. SPLIT lv_search AT `&` INTO TABLE DATA(lt_param). diff --git a/src/02/z2ui5_cl_smps_app_319.clas.abap b/src/02/z2ui5_cl_smps_app_319.clas.abap index cd29198..865765f 100644 --- a/src/02/z2ui5_cl_smps_app_319.clas.abap +++ b/src/02/z2ui5_cl_smps_app_319.clas.abap @@ -267,6 +267,7 @@ CLASS z2ui5_cl_smps_app_319 IMPLEMENTATION. DATA option TYPE c LENGTH 2. DATA low TYPE string. DATA high TYPE string. + DATA skipped TYPE i. t_selopt = VALUE #( ). lr_type = VALUE #( ). @@ -277,21 +278,37 @@ CLASS z2ui5_cl_smps_app_319 IMPLEMENTATION. low = s-value1. high = s-value2. - CASE to_upper( s-operation ). - WHEN `EQ`. option = `EQ`. - WHEN `NE`. option = `NE`. - WHEN `CONTAINS`. option = `CP`. low = |*{ s-value1 }*|. - WHEN `NOTCONTAINS`. option = `CP`. low = |*{ s-value1 }*|. sign = `E`. - WHEN `STARTSWITH`. option = `CP`. low = |{ s-value1 }*|. - WHEN `ENDSWITH`. option = `CP`. low = |*{ s-value1 }|. - WHEN `BT`. option = `BT`. - WHEN `NB`. option = `NB`. - WHEN `GT`. option = `GT`. - WHEN `GE`. option = `GE`. - WHEN `LT`. option = `LT`. - WHEN `LE`. option = `LE`. - WHEN `EMPTY`. option = `EQ`. low = ``. - WHEN OTHERS. option = `EQ`. + " the Not* operations (NotEQ, NotBT, NotContains, NotEmpty, ...) are + " their positive twin with the sign turned round - read as EQ, they + " selected exactly the rows the user had asked to leave out + DATA(operation) = to_upper( s-operation ). + IF strlen( operation ) > 3 AND substring( val = operation len = 3 ) = `NOT`. + operation = substring( val = operation off = 3 ). + sign = COND #( WHEN sign = `I` THEN `E` ELSE `I` ). + ENDIF. + + CASE operation. + WHEN `EQ` OR ``. option = `EQ`. + WHEN `NE`. option = `NE`. + WHEN `CONTAINS`. option = `CP`. low = |*{ s-value1 }*|. + WHEN `STARTSWITH`. option = `CP`. low = |{ s-value1 }*|. + WHEN `ENDSWITH`. option = `CP`. low = |*{ s-value1 }|. + WHEN `BT`. option = `BT`. + WHEN `NB`. option = `NB`. + WHEN `GT`. option = `GT`. + WHEN `GE`. option = `GE`. + WHEN `LT`. option = `LT`. + WHEN `LE`. option = `LE`. + WHEN `EMPTY` OR `INITIAL`. + option = `EQ`. + low = ``. + high = ``. + WHEN OTHERS. + " an operation this mapping does not know is left out rather than + " guessed - an EQ on its first value would filter on something the + " user never asked for + skipped = skipped + 1. + CONTINUE. ENDCASE. APPEND VALUE #( sign = sign option = option low = low high = high ) TO lr_type. @@ -309,6 +326,9 @@ CLASS z2ui5_cl_smps_app_319 IMPLEMENTATION. ENDLOOP. hint = |{ lines( t_selopt ) } condition(s) -> { lines( t_result ) } of { lines( t_product ) } demo products match.|. ENDIF. + IF skipped > 0. + hint = |{ hint } { skipped } condition(s) with an operation this sample does not map were left out.|. + ENDIF. ENDMETHOD. diff --git a/src/07/z2ui5_cl_smps_app_489.clas.abap b/src/07/z2ui5_cl_smps_app_489.clas.abap index 041e9e2..42ccddb 100644 --- a/src/07/z2ui5_cl_smps_app_489.clas.abap +++ b/src/07/z2ui5_cl_smps_app_489.clas.abap @@ -52,6 +52,14 @@ CLASS z2ui5_cl_smps_app_489 DEFINITION PUBLIC. RETURNING VALUE(result) TYPE string. + "! the three characters FormattedText reads as markup - escaped, so a + "! news item somebody else posted shows the text they typed + METHODS html_escape + IMPORTING + val TYPE string + RETURNING + VALUE(result) TYPE string. + ENDCLASS. @@ -148,9 +156,12 @@ CLASS z2ui5_cl_smps_app_489 IMPLEMENTATION. RETURN. ENDIF. + " a FeedListItem renders its text as FormattedText, and this text + " was typed by whoever is on the channel - escaped, so a posted + " or reaches the other sessions as the text it is INSERT VALUE ty_s_news( - text = json_get_string( json = ws_message - name = `text` ) + text = html_escape( json_get_string( json = ws_message + name = `text` ) ) author = json_get_string( json = ws_message name = `author` ) ) INTO TABLE t_news. @@ -194,6 +205,16 @@ CLASS z2ui5_cl_smps_app_489 IMPLEMENTATION. ENDMETHOD. + METHOD html_escape. + + " the ampersand FIRST, or the other two would be escaped twice + result = replace( val = val sub = `&` with = `&` occ = 0 ). + result = replace( val = result sub = `<` with = `<` occ = 0 ). + result = replace( val = result sub = `>` with = `>` occ = 0 ). + + ENDMETHOD. + + METHOD json_get_string. " Reads one string field of the flat object json_build( ) writes. Finding diff --git a/src/10/z2ui5_cl_smps_app_013.clas.abap b/src/10/z2ui5_cl_smps_app_013.clas.abap index 2f7ff5c..cf718e2 100644 --- a/src/10/z2ui5_cl_smps_app_013.clas.abap +++ b/src/10/z2ui5_cl_smps_app_013.clas.abap @@ -97,6 +97,11 @@ CLASS z2ui5_cl_smps_app_013 IMPLEMENTATION. TRY. z2ui5_cl_smps_llm_factory=>config_save( config_from_form( ) ). model_init( ). + " the strip reported an earlier test or a failed save - neither is + " true of the configuration that was just saved + CLEAR result_text. + result_type = `Information`. + result_visible = abap_false. client->message_toast_display( `Settings saved` ). CATCH z2ui5_cx_smps_llm INTO DATA(error). diff --git a/src/z2ui5_cl_smps_app_000.clas.abap b/src/z2ui5_cl_smps_app_000.clas.abap index fe84077..930dc78 100644 --- a/src/z2ui5_cl_smps_app_000.clas.abap +++ b/src/z2ui5_cl_smps_app_000.clas.abap @@ -1072,33 +1072,53 @@ CLASS z2ui5_cl_smps_app_000 IMPLEMENTATION. METHOD url_param_get_tab. - DATA(lv_search) = replace( val = val - sub = `%3D` - with = `=` - occ = 0 ). - - " RFC 3986 allows lowercase hex digits in percent-encodings, so decode - " %3d the same way as %3D (%26 contains no letters and needs no twin) - lv_search = replace( val = lv_search - sub = `%3d` - with = `=` - occ = 0 ). - - lv_search = replace( val = lv_search - sub = `%26` - with = `&` - occ = 0 ). - - lv_search = shift_left( val = lv_search sub = `?` ). - - " prepend & before searching so sap-startup-params is also unwrapped - " when it is the first/only query parameter (typical FLP target mapping) - DATA(lv_search2) = substring_after( val = |&{ lv_search }| sub = `&sap-startup-params=` ). - lv_search = COND #( WHEN lv_search2 IS NOT INITIAL THEN lv_search2 ELSE lv_search ). - - lv_search2 = substring_after( val = lv_search sub = `?` ). - IF lv_search2 IS NOT INITIAL. - lv_search = lv_search2. + " a full URL or a request URI carries a path before its query: cut at + " the FIRST `?` only. A later `?` is a legal, unencoded character of a + " value (`title=why?`) - cutting there dropped every parameter before it + " declared, not inline: DATA( ) from a generic CLIKE parameter is "fixed + " type STRING used for generic type CLIKE" in the extended check + DATA lv_search TYPE string. + lv_search = val. + IF lv_search CS `?`. + lv_search = substring_after( val = lv_search sub = `?` ). + ENDIF. + + " The FLP packs the target's own parameters into ONE value, + " sap-startup-params, with its `=` and `&` percent-encoded. Prepend & + " before searching so it is also unwrapped when it is the first/only + " query parameter (typical FLP target mapping). Only THAT value is + " decoded: decoding the whole query first tore every legitimately encoded + " `&` or `=` in any other value apart (`a=x%26y` became a=x and y=), and + " what stands BEFORE the wrapper - sap-client, sap-language - is kept: + " it used to be dropped from every link built from this table + " (abap2UI5's z2ui5_cl_ui5_util_context carries the same fix) + DATA(lv_startup) = substring_after( val = |&{ lv_search }| sub = `&sap-startup-params=` ). + IF lv_startup IS NOT INITIAL. + " lv_before keeps the prepended `&`, so the empty first segment it + " produces below is skipped like a trailing one + DATA(lv_before) = substring_before( val = |&{ lv_search }| sub = `&sap-startup-params=` ). + SPLIT lv_startup AT `&` INTO DATA(lv_packed) DATA(lv_rest). + lv_packed = replace( val = lv_packed + sub = `%3D` + with = `=` + occ = 0 ). + " RFC 3986 allows lowercase hex digits in percent-encodings, so decode + " %3d the same way as %3D (%26 contains no letters and needs no twin) + lv_packed = replace( val = lv_packed + sub = `%3d` + with = `=` + occ = 0 ). + lv_packed = replace( val = lv_packed + sub = `%26` + with = `&` + occ = 0 ). + lv_search = lv_packed. + IF lv_rest IS NOT INITIAL. + lv_search = |{ lv_packed }&{ lv_rest }|. + ENDIF. + IF lv_before IS NOT INITIAL. + lv_search = |{ lv_before }&{ lv_search }|. + ENDIF. ENDIF. SPLIT lv_search AT `&` INTO TABLE DATA(lt_param).