From 55fb0d07a462d0054e06f555710bd1bd92196832 Mon Sep 17 00:00:00 2001 From: Lars Hvam Date: Fri, 25 Aug 2023 07:14:03 +0200 Subject: [PATCH] more ui core decoupling (#6374) Co-authored-by: Marc Bernard <59966492+mbtools@users.noreply.github.com> --- abaplint.json | 1 + src/ui/core/zcl_abapgit_gui_event.clas.abap | 176 ++++++++- ...cl_abapgit_gui_event.clas.testclasses.abap | 368 +++++++++++++++++- .../zcl_abapgit_html_action_utils.clas.abap | 170 +------- ...it_html_action_utils.clas.testclasses.abap | 363 ----------------- .../zcl_abapgit_html_action_utils.clas.xml | 1 - 6 files changed, 540 insertions(+), 539 deletions(-) delete mode 100644 src/ui/lib/zcl_abapgit_html_action_utils.clas.testclasses.abap diff --git a/abaplint.json b/abaplint.json index 93f11afaf..890533728 100644 --- a/abaplint.json +++ b/abaplint.json @@ -236,6 +236,7 @@ "7bit_ascii": { "exclude": [ "zcl_abapgit_git_commit.clas.testclasses.abap", + "zcl_abapgit_gui_event.clas.testclasses.abap", "zcl_abapgit_html_action_utils.clas.testclasses.abap" ] }, diff --git a/src/ui/core/zcl_abapgit_gui_event.clas.abap b/src/ui/core/zcl_abapgit_gui_event.clas.abap index c9ce52533..a005d5bfe 100644 --- a/src/ui/core/zcl_abapgit_gui_event.clas.abap +++ b/src/ui/core/zcl_abapgit_gui_event.clas.abap @@ -7,6 +7,8 @@ CLASS zcl_abapgit_gui_event DEFINITION INTERFACES zif_abapgit_gui_event . + CLASS-METHODS class_constructor . + CLASS-METHODS new IMPORTING !ii_gui_services TYPE REF TO zif_abapgit_gui_services OPTIONAL @@ -26,6 +28,8 @@ CLASS zcl_abapgit_gui_event DEFINITION DATA mo_query TYPE REF TO zcl_abapgit_string_map. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. + CLASS-DATA gv_non_breaking_space TYPE string . + METHODS fields_to_map IMPORTING it_fields TYPE tihttpnvp @@ -34,6 +38,40 @@ CLASS zcl_abapgit_gui_event DEFINITION RAISING zcx_abapgit_exception. + CLASS-METHODS parse_post_form_data + IMPORTING + !it_post_data TYPE zif_abapgit_html_viewer=>ty_post_data + !iv_upper_cased TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_fields) TYPE tihttpnvp . + CLASS-METHODS parse_fields + IMPORTING + !iv_string TYPE clike + !iv_upper_cased TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(rt_fields) TYPE tihttpnvp . + + CLASS-METHODS parse_fields_upper_case_name + IMPORTING + !iv_string TYPE clike + RETURNING + VALUE(rt_fields) TYPE tihttpnvp . + + CLASS-METHODS translate_postdata + IMPORTING + !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data + RETURNING + VALUE(rv_string) TYPE string . + + CLASS-METHODS field_keys_to_upper + CHANGING + !ct_fields TYPE tihttpnvp . + CLASS-METHODS unescape + IMPORTING + !iv_string TYPE string + RETURNING + VALUE(rv_string) TYPE string . + ENDCLASS. @@ -81,8 +119,7 @@ CLASS zcl_abapgit_gui_event IMPLEMENTATION. METHOD zif_abapgit_gui_event~form_data. IF mo_form_data IS NOT BOUND. - mo_form_data = fields_to_map( - zcl_abapgit_html_action_utils=>parse_post_form_data( zif_abapgit_gui_event~mt_postdata ) ). + mo_form_data = fields_to_map( parse_post_form_data( zif_abapgit_gui_event~mt_postdata ) ). mo_form_data->freeze( ). ENDIF. ro_string_map = mo_form_data. @@ -93,11 +130,142 @@ CLASS zcl_abapgit_gui_event IMPLEMENTATION. METHOD zif_abapgit_gui_event~query. IF mo_query IS NOT BOUND. - mo_query = fields_to_map( - zcl_abapgit_html_action_utils=>parse_fields( zif_abapgit_gui_event~mv_getdata ) ). + mo_query = fields_to_map( parse_fields( zif_abapgit_gui_event~mv_getdata ) ). mo_query->freeze( ). ENDIF. ro_string_map = mo_query. ENDMETHOD. + + METHOD parse_fields_upper_case_name. + + rt_fields = parse_fields( + iv_string = iv_string + iv_upper_cased = abap_true ). + + ENDMETHOD. + + + METHOD parse_post_form_data. + + DATA lv_serialized_post_data TYPE string. + + lv_serialized_post_data = translate_postdata( it_post_data ). + IF iv_upper_cased = abap_true. + rt_fields = parse_fields_upper_case_name( lv_serialized_post_data ). + ELSE. + rt_fields = parse_fields( lv_serialized_post_data ). + ENDIF. + + ENDMETHOD. + + METHOD parse_fields. + + DATA: + lt_substrings TYPE string_table, + ls_field LIKE LINE OF rt_fields. + + FIELD-SYMBOLS LIKE LINE OF lt_substrings. + + SPLIT iv_string AT '&' INTO TABLE lt_substrings. + + LOOP AT lt_substrings ASSIGNING . + + CLEAR ls_field. + " On attempt to change unescaping -> run unit tests to check ! + + " Unescape name and value separately + ls_field-name = unescape( substring_before( + val = + sub = '=' ) ). + + ls_field-value = unescape( substring_after( + val = + sub = '=' ) ). + + IF ls_field IS INITIAL. " Not a field with proper structure + CONTINUE. + ENDIF. + + APPEND ls_field TO rt_fields. + + ENDLOOP. + + IF iv_upper_cased = abap_true. + field_keys_to_upper( CHANGING ct_fields = rt_fields ). + ENDIF. + + ENDMETHOD. + + + METHOD translate_postdata. + + DATA: lt_post_data TYPE zif_abapgit_html_viewer=>ty_post_data, + ls_last_line LIKE LINE OF it_postdata, + lv_last_line_index TYPE i. + + IF it_postdata IS INITIAL. + RETURN. "Nothing to do + ENDIF. + + lt_post_data = it_postdata. + + "Save the last line for separate merge, because we don't need its trailing spaces + WHILE ls_last_line IS INITIAL. + lv_last_line_index = lines( lt_post_data ). + READ TABLE lt_post_data INTO ls_last_line INDEX lv_last_line_index. + "Avoid trailing null values (see isssue #4832) + "todo, keep until SAP GUI for Java is fixed (remove on 2022-12-31) + ls_last_line = replace( val = ls_last_line + sub = zcl_abapgit_git_utils=>get_null( ) + with = space + occ = 0 ). + DELETE lt_post_data INDEX lv_last_line_index. + ENDWHILE. + + CONCATENATE LINES OF lt_post_data INTO rv_string + IN CHARACTER MODE RESPECTING BLANKS. + CONCATENATE rv_string ls_last_line INTO rv_string + IN CHARACTER MODE. + + ENDMETHOD. + + METHOD field_keys_to_upper. + + FIELD-SYMBOLS LIKE LINE OF ct_fields. + + LOOP AT ct_fields ASSIGNING . + -name = to_upper( -name ). + ENDLOOP. + + ENDMETHOD. + + METHOD unescape. + +* do not use cl_http_utility as it does strange things with the encoding + rv_string = iv_string. + +* todo, more to be added here + REPLACE ALL OCCURRENCES OF '%3A' IN rv_string WITH ':' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%3F' IN rv_string WITH '?' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%3D' IN rv_string WITH '=' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%2F' IN rv_string WITH '/' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%25' IN rv_string WITH '%' IGNORING CASE. + REPLACE ALL OCCURRENCES OF '%26' IN rv_string WITH '&' IGNORING CASE. + REPLACE ALL OCCURRENCES OF gv_non_breaking_space IN rv_string WITH ` `. + + ENDMETHOD. + + METHOD class_constructor. + + CONSTANTS lc_nbsp TYPE xstring VALUE 'C2A0'. "   + + TRY. + gv_non_breaking_space = zcl_abapgit_convert=>xstring_to_string_utf8( lc_nbsp ). + CATCH zcx_abapgit_exception. + ASSERT 0 = 1. + ENDTRY. + + ENDMETHOD. + ENDCLASS. diff --git a/src/ui/core/zcl_abapgit_gui_event.clas.testclasses.abap b/src/ui/core/zcl_abapgit_gui_event.clas.testclasses.abap index deae21a77..d0e7a5db4 100644 --- a/src/ui/core/zcl_abapgit_gui_event.clas.testclasses.abap +++ b/src/ui/core/zcl_abapgit_gui_event.clas.testclasses.abap @@ -23,7 +23,7 @@ CLASS ltcl_event IMPLEMENTATION. CREATE OBJECT li_cut TYPE zcl_abapgit_gui_event EXPORTING - iv_action = 'XXX' + iv_action = 'XXX' iv_getdata = 'not_a_param'. lo_map = li_cut->query( ). @@ -56,7 +56,7 @@ CLASS ltcl_event IMPLEMENTATION. CREATE OBJECT li_cut TYPE zcl_abapgit_gui_event EXPORTING - iv_action = 'XXX' + iv_action = 'XXX' iv_getdata = 'a=b&b=c'. " Cross check just in case @@ -163,3 +163,367 @@ CLASS ltcl_event IMPLEMENTATION. ENDMETHOD. ENDCLASS. + +CLASS ltcl_html_action_utils DEFINITION FOR TESTING RISK LEVEL HARMLESS + DURATION SHORT FINAL. + + PUBLIC SECTION. + + CLASS-METHODS class_constructor. + METHODS parse_fields_simple_case FOR TESTING. + METHODS parse_fields_advanced_case FOR TESTING. + METHODS parse_fields_unescape FOR TESTING. + METHODS parse_fields_unescape_nbsp FOR TESTING. + METHODS parse_fields_german_umlauts FOR TESTING. + METHODS parse_fields_wrong_format FOR TESTING. + METHODS parse_post_form_data FOR TESTING. + METHODS parse_fields_webgui FOR TESTING. + METHODS parse_fields_special_chars FOR TESTING. + + PRIVATE SECTION. + + CONSTANTS: BEGIN OF c_german_umlaut_as_hex, + lower_case_ae TYPE xstring VALUE 'C3A4', + lower_case_oe TYPE xstring VALUE 'C3B6', + lower_case_ue TYPE xstring VALUE 'C3BC', + END OF c_german_umlaut_as_hex. + + CLASS-DATA: BEGIN OF gs_german_umlaut_as_char, + lower_case_ae TYPE string, + lower_case_oe TYPE string, + lower_case_ue TYPE string, + END OF gs_german_umlaut_as_char. + + DATA mv_given_parse_string TYPE string. + DATA mt_parsed_fields TYPE tihttpnvp. + + METHODS _given_string_is + IMPORTING + iv_string TYPE string. + METHODS _when_fields_are_parsed_upper. + METHODS _when_fields_are_parsed. + METHODS _then_fields_should_be + IMPORTING + iv_index TYPE i + iv_name TYPE string + iv_value TYPE string. + METHODS _then_field_count_should_be + IMPORTING + iv_count TYPE i. + + CLASS-METHODS _hex_to_char + IMPORTING + iv_x TYPE xstring + RETURNING + VALUE(rv_s) TYPE string. + +ENDCLASS. + +CLASS zcl_abapgit_gui_event DEFINITION LOCAL FRIENDS ltcl_html_action_utils. + +CLASS ltcl_html_action_utils IMPLEMENTATION. + + METHOD class_constructor. + + gs_german_umlaut_as_char-lower_case_ae = _hex_to_char( c_german_umlaut_as_hex-lower_case_ae ). + gs_german_umlaut_as_char-lower_case_oe = _hex_to_char( c_german_umlaut_as_hex-lower_case_oe ). + gs_german_umlaut_as_char-lower_case_ue = _hex_to_char( c_german_umlaut_as_hex-lower_case_ue ). + + ENDMETHOD. + + METHOD parse_fields_simple_case. + + _given_string_is( `committer_name=Gustav Gans` ). + + _when_fields_are_parsed_upper( ). + + _then_fields_should_be( iv_index = 1 + iv_name = `COMMITTER_NAME` + iv_value = `Gustav Gans` ). + + ENDMETHOD. + + METHOD parse_fields_advanced_case. + + _given_string_is( `committer_name=Albert Schweitzer&` + && `committer_email=albert.schweitzer@googlemail.com&` + && `comment=dummy comment&` + && `body=Message body<><>with line break<>&` + && `author_name=Karl Klammer&` + && `author_email=karl@klammer.com` ). + + _when_fields_are_parsed_upper( ). + + _then_fields_should_be( iv_index = 1 + iv_name = `COMMITTER_NAME` + iv_value = `Albert Schweitzer` ). + + _then_fields_should_be( iv_index = 2 + iv_name = `COMMITTER_EMAIL` + iv_value = `albert.schweitzer@googlemail.com` ). + + _then_fields_should_be( iv_index = 3 + iv_name = `COMMENT` + iv_value = `dummy comment` ). + + _then_fields_should_be( iv_index = 4 + iv_name = `BODY` + iv_value = `Message body<><>with line break<>` ). + + _then_fields_should_be( iv_index = 5 + iv_name = `AUTHOR_NAME` + iv_value = `Karl Klammer` ). + + _then_fields_should_be( iv_index = 6 + iv_name = `AUTHOR_EMAIL` + iv_value = `karl@klammer.com` ). + + ENDMETHOD. + + METHOD parse_fields_unescape. + + " file status = '?', used in staging page + _given_string_is( '/SRC/ZFOOBAR.PROG.ABAP=%3F' ). + + _when_fields_are_parsed_upper( ). + _then_field_count_should_be( 1 ). + + _then_fields_should_be( + iv_index = 1 + iv_name = '/SRC/ZFOOBAR.PROG.ABAP' + iv_value = '?' ). + + ENDMETHOD. + + METHOD parse_fields_unescape_nbsp. + + " non-breaking space ( ) + _given_string_is( '/src/ztest_rfc.fugr.xml=%3F&/src/ztest_rfc' + && zcl_abapgit_gui_event=>gv_non_breaking_space + && zcl_abapgit_gui_event=>gv_non_breaking_space + && zcl_abapgit_gui_event=>gv_non_breaking_space + && 'rf.sush.xml=A' ). + + _when_fields_are_parsed( ). + _then_field_count_should_be( 2 ). + + _then_fields_should_be( + iv_index = 1 + iv_name = '/src/ztest_rfc.fugr.xml' + iv_value = '?' ). + + _then_fields_should_be( + iv_index = 2 + iv_name = '/src/ztest_rfc rf.sush.xml' + iv_value = 'A' ). + + ENDMETHOD. + + METHOD parse_fields_german_umlauts. + + DATA: lv_ae TYPE string, + lv_oe TYPE string, + lv_ue TYPE string, + lv_ae_oe_ue TYPE string. + + + lv_ae = gs_german_umlaut_as_char-lower_case_ae. + lv_oe = gs_german_umlaut_as_char-lower_case_oe. + lv_ue = gs_german_umlaut_as_char-lower_case_ue. + + lv_ae_oe_ue = lv_ae && lv_oe && lv_ue. + + _given_string_is( |committer_name=Christian G{ lv_ue }nter&| + && |committer_email=guenne@googlemail.com&| + && |comment={ lv_ae_oe_ue }&| + && |body=Message body<><>with line break<>and umlauts. { lv_ae_oe_ue }&| + && |author_name=Gerd Schr{ lv_oe }der&| + && |author_email=gerd@schroeder.com| ). + + _when_fields_are_parsed_upper( ). + + _then_fields_should_be( iv_index = 1 + iv_name = `COMMITTER_NAME` + iv_value = |Christian G{ lv_ue }nter| ). + + _then_fields_should_be( iv_index = 2 + iv_name = `COMMITTER_EMAIL` + iv_value = `guenne@googlemail.com` ). + + _then_fields_should_be( iv_index = 3 + iv_name = `COMMENT` + iv_value = lv_ae_oe_ue ). + + _then_fields_should_be( iv_index = 4 + iv_name = `BODY` + iv_value = |Message body<><>with line break<>and umlauts. { lv_ae_oe_ue }| ). + + _then_fields_should_be( iv_index = 5 + iv_name = `AUTHOR_NAME` + iv_value = |Gerd Schr{ lv_oe }der| ). + + _then_fields_should_be( iv_index = 6 + iv_name = `AUTHOR_EMAIL` + iv_value = `gerd@schroeder.com` ). + + ENDMETHOD. + + METHOD _given_string_is. + + mv_given_parse_string = iv_string. + + ENDMETHOD. + + METHOD _when_fields_are_parsed_upper. + + mt_parsed_fields = zcl_abapgit_gui_event=>parse_fields_upper_case_name( mv_given_parse_string ). + + ENDMETHOD. + + METHOD _when_fields_are_parsed. + + mt_parsed_fields = zcl_abapgit_gui_event=>parse_fields( mv_given_parse_string ). + + ENDMETHOD. + + METHOD _then_fields_should_be. + + FIELD-SYMBOLS: LIKE LINE OF mt_parsed_fields. + + READ TABLE mt_parsed_fields ASSIGNING INDEX iv_index. + + cl_abap_unit_assert=>assert_subrc( + exp = 0 + msg = |No parsed field found at index { iv_index }| ). + + cl_abap_unit_assert=>assert_equals( + act = -name + exp = iv_name + msg = |Name at index { iv_index } should be { iv_name }| ). + + cl_abap_unit_assert=>assert_equals( + act = -value + exp = iv_value + msg = |Value at index { iv_index } should be { iv_value }| ). + + ENDMETHOD. + + METHOD _then_field_count_should_be. + + cl_abap_unit_assert=>assert_equals( + act = lines( mt_parsed_fields ) + exp = iv_count + msg = |Field count { lines( mt_parsed_fields ) } should be { iv_count }| ). + + ENDMETHOD. + + METHOD _hex_to_char. + + DATA lo_conv TYPE REF TO cl_abap_conv_in_ce. + + lo_conv = cl_abap_conv_in_ce=>create( ). + lo_conv->convert( EXPORTING input = iv_x IMPORTING data = rv_s ). + + ENDMETHOD. + + METHOD parse_fields_wrong_format. + + _given_string_is( `some_query_string_without_param_structure` ). + _when_fields_are_parsed_upper( ). + _then_field_count_should_be( 0 ). + + _given_string_is( `some_query_string_without_param_structure&a=b` ). + _when_fields_are_parsed_upper( ). + _then_field_count_should_be( 1 ). + _then_fields_should_be( + iv_index = 1 + iv_name = 'A' + iv_value = 'b' ). + + ENDMETHOD. + + METHOD parse_post_form_data. + + DATA lt_post_data TYPE zif_abapgit_html_viewer=>ty_post_data. + DATA lv_line LIKE LINE OF lt_post_data. + DATA lv_long_name LIKE LINE OF lt_post_data. + DATA lv_size TYPE i. + + DESCRIBE FIELD lv_line LENGTH lv_size IN CHARACTER MODE. + lv_long_name = repeat( + val = 'x' + occ = lv_size - 4 ). + lv_line = 'a=b&' && lv_long_name. + + APPEND lv_line TO lt_post_data. + APPEND '=y' TO lt_post_data. + + mt_parsed_fields = zcl_abapgit_gui_event=>parse_post_form_data( lt_post_data ). + _then_field_count_should_be( 2 ). + _then_fields_should_be( + iv_index = 1 + iv_name = 'a' + iv_value = 'b' ). + _then_fields_should_be( + iv_index = 2 + iv_name = |{ lv_long_name }| + iv_value = 'y' ). + + mt_parsed_fields = zcl_abapgit_gui_event=>parse_post_form_data( + it_post_data = lt_post_data + iv_upper_cased = abap_true ). + _then_field_count_should_be( 2 ). + _then_fields_should_be( + iv_index = 1 + iv_name = 'A' + iv_value = 'b' ). + _then_fields_should_be( + iv_index = 2 + iv_name = |{ to_upper( lv_long_name ) }| + iv_value = 'y' ). + + ENDMETHOD. + + + METHOD parse_fields_webgui. + + _given_string_is( `KEY=000000000019&PATH=%2fsrc%2f&FILENAME=%2fnsp%2ftest_ddls_bug2.ddls.asddls` ). + _when_fields_are_parsed( ). + _then_field_count_should_be( 3 ). + + _then_fields_should_be( + iv_index = 1 + iv_name = 'KEY' + iv_value = '000000000019' ). + + _then_fields_should_be( + iv_index = 2 + iv_name = 'PATH' + iv_value = '/src/' ). + + _then_fields_should_be( + iv_index = 3 + iv_name = 'FILENAME' + iv_value = '/nsp/test_ddls_bug2.ddls.asddls' ). + + ENDMETHOD. + + METHOD parse_fields_special_chars. + + DATA lv_string TYPE string. + + " URL encoded data + lv_string = `TEST=!"#$%25%26'()*+,-./09:;<%3d>?@AZ[\]^_``az{|}~¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿`. + + _given_string_is( lv_string ). + _when_fields_are_parsed( ). + _then_field_count_should_be( 1 ). + + _then_fields_should_be( + iv_index = 1 + iv_name = 'TEST' + iv_value = `!"#$%&'()*+,-./09:;<=>?@AZ[\]^_``az{|}~¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿` ). + + ENDMETHOD. + +ENDCLASS. diff --git a/src/ui/lib/zcl_abapgit_html_action_utils.clas.abap b/src/ui/lib/zcl_abapgit_html_action_utils.clas.abap index 6adf7d099..b7727760b 100644 --- a/src/ui/lib/zcl_abapgit_html_action_utils.clas.abap +++ b/src/ui/lib/zcl_abapgit_html_action_utils.clas.abap @@ -4,18 +4,6 @@ CLASS zcl_abapgit_html_action_utils DEFINITION PUBLIC SECTION. - CLASS-METHODS parse_post_form_data - IMPORTING - !it_post_data TYPE zif_abapgit_html_viewer=>ty_post_data - !iv_upper_cased TYPE abap_bool DEFAULT abap_false - RETURNING - VALUE(rt_fields) TYPE tihttpnvp . - CLASS-METHODS parse_fields - IMPORTING - !iv_string TYPE clike - !iv_upper_cased TYPE abap_bool DEFAULT abap_false - RETURNING - VALUE(rt_fields) TYPE tihttpnvp . CLASS-METHODS jump_encode IMPORTING !iv_obj_type TYPE tadir-object @@ -40,7 +28,6 @@ CLASS zcl_abapgit_html_action_utils DEFINITION !ig_object TYPE any RETURNING VALUE(rv_string) TYPE string . - CLASS-METHODS class_constructor . CLASS-METHODS dbkey_encode IMPORTING !is_key TYPE zif_abapgit_persistence=>ty_content @@ -49,37 +36,17 @@ CLASS zcl_abapgit_html_action_utils DEFINITION PROTECTED SECTION. PRIVATE SECTION. - CLASS-DATA gv_non_breaking_space TYPE string . - - CLASS-METHODS parse_fields_upper_case_name - IMPORTING - !iv_string TYPE clike - RETURNING - VALUE(rt_fields) TYPE tihttpnvp . - CLASS-METHODS translate_postdata - IMPORTING - !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data - RETURNING - VALUE(rv_string) TYPE string . - CLASS-METHODS field_keys_to_upper - CHANGING - !ct_fields TYPE tihttpnvp . CLASS-METHODS add_field IMPORTING !iv_name TYPE string !ig_field TYPE any CHANGING !ct_field TYPE tihttpnvp . - CLASS-METHODS unescape - IMPORTING - !iv_string TYPE string - RETURNING - VALUE(rv_string) TYPE string . ENDCLASS. -CLASS ZCL_ABAPGIT_HTML_ACTION_UTILS IMPLEMENTATION. +CLASS zcl_abapgit_html_action_utils IMPLEMENTATION. METHOD add_field. @@ -106,19 +73,6 @@ CLASS ZCL_ABAPGIT_HTML_ACTION_UTILS IMPLEMENTATION. ENDMETHOD. - METHOD class_constructor. - - CONSTANTS lc_nbsp TYPE xstring VALUE 'C2A0'. "   - - TRY. - gv_non_breaking_space = zcl_abapgit_convert=>xstring_to_string_utf8( lc_nbsp ). - CATCH zcx_abapgit_exception. - ASSERT 0 = 1. - ENDTRY. - - ENDMETHOD. - - METHOD dbkey_encode. DATA: lt_fields TYPE tihttpnvp. @@ -143,17 +97,6 @@ CLASS ZCL_ABAPGIT_HTML_ACTION_UTILS IMPLEMENTATION. ENDMETHOD. - METHOD field_keys_to_upper. - - FIELD-SYMBOLS LIKE LINE OF ct_fields. - - LOOP AT ct_fields ASSIGNING . - -name = to_upper( -name ). - ENDLOOP. - - ENDMETHOD. - - METHOD file_encode. DATA: lt_fields TYPE tihttpnvp. @@ -207,115 +150,4 @@ CLASS ZCL_ABAPGIT_HTML_ACTION_UTILS IMPLEMENTATION. ENDMETHOD. - - METHOD parse_fields. - - DATA: - lt_substrings TYPE string_table, - ls_field LIKE LINE OF rt_fields. - - FIELD-SYMBOLS LIKE LINE OF lt_substrings. - - SPLIT iv_string AT '&' INTO TABLE lt_substrings. - - LOOP AT lt_substrings ASSIGNING . - - CLEAR ls_field. - " On attempt to change unescaping -> run unit tests to check ! - - " Unescape name and value separately - ls_field-name = unescape( substring_before( - val = - sub = '=' ) ). - - ls_field-value = unescape( substring_after( - val = - sub = '=' ) ). - - IF ls_field IS INITIAL. " Not a field with proper structure - CONTINUE. - ENDIF. - - APPEND ls_field TO rt_fields. - - ENDLOOP. - - IF iv_upper_cased = abap_true. - field_keys_to_upper( CHANGING ct_fields = rt_fields ). - ENDIF. - - ENDMETHOD. - - - METHOD parse_fields_upper_case_name. - - rt_fields = parse_fields( - iv_string = iv_string - iv_upper_cased = abap_true ). - - ENDMETHOD. - - - METHOD parse_post_form_data. - - DATA lv_serialized_post_data TYPE string. - - lv_serialized_post_data = translate_postdata( it_post_data ). - IF iv_upper_cased = abap_true. - rt_fields = parse_fields_upper_case_name( lv_serialized_post_data ). - ELSE. - rt_fields = parse_fields( lv_serialized_post_data ). - ENDIF. - - ENDMETHOD. - - - METHOD translate_postdata. - - DATA: lt_post_data TYPE zif_abapgit_html_viewer=>ty_post_data, - ls_last_line LIKE LINE OF it_postdata, - lv_last_line_index TYPE i. - - IF it_postdata IS INITIAL. - RETURN. "Nothing to do - ENDIF. - - lt_post_data = it_postdata. - - "Save the last line for separate merge, because we don't need its trailing spaces - WHILE ls_last_line IS INITIAL. - lv_last_line_index = lines( lt_post_data ). - READ TABLE lt_post_data INTO ls_last_line INDEX lv_last_line_index. - "Avoid trailing null values (see isssue #4832) - "todo, keep until SAP GUI for Java is fixed (remove on 2022-12-31) - ls_last_line = replace( val = ls_last_line - sub = zcl_abapgit_git_utils=>get_null( ) - with = space - occ = 0 ). - DELETE lt_post_data INDEX lv_last_line_index. - ENDWHILE. - - CONCATENATE LINES OF lt_post_data INTO rv_string - IN CHARACTER MODE RESPECTING BLANKS. - CONCATENATE rv_string ls_last_line INTO rv_string - IN CHARACTER MODE. - - ENDMETHOD. - - - METHOD unescape. - -* do not use cl_http_utility as it does strange things with the encoding - rv_string = iv_string. - -* todo, more to be added here - REPLACE ALL OCCURRENCES OF '%3A' IN rv_string WITH ':' IGNORING CASE. - REPLACE ALL OCCURRENCES OF '%3F' IN rv_string WITH '?' IGNORING CASE. - REPLACE ALL OCCURRENCES OF '%3D' IN rv_string WITH '=' IGNORING CASE. - REPLACE ALL OCCURRENCES OF '%2F' IN rv_string WITH '/' IGNORING CASE. - REPLACE ALL OCCURRENCES OF '%25' IN rv_string WITH '%' IGNORING CASE. - REPLACE ALL OCCURRENCES OF '%26' IN rv_string WITH '&' IGNORING CASE. - REPLACE ALL OCCURRENCES OF gv_non_breaking_space IN rv_string WITH ` `. - - ENDMETHOD. ENDCLASS. diff --git a/src/ui/lib/zcl_abapgit_html_action_utils.clas.testclasses.abap b/src/ui/lib/zcl_abapgit_html_action_utils.clas.testclasses.abap deleted file mode 100644 index f5f2450fa..000000000 --- a/src/ui/lib/zcl_abapgit_html_action_utils.clas.testclasses.abap +++ /dev/null @@ -1,363 +0,0 @@ -CLASS ltcl_html_action_utils DEFINITION FOR TESTING RISK LEVEL HARMLESS - DURATION SHORT FINAL. - - PUBLIC SECTION. - - CLASS-METHODS class_constructor. - METHODS parse_fields_simple_case FOR TESTING. - METHODS parse_fields_advanced_case FOR TESTING. - METHODS parse_fields_unescape FOR TESTING. - METHODS parse_fields_unescape_nbsp FOR TESTING. - METHODS parse_fields_german_umlauts FOR TESTING. - METHODS parse_fields_wrong_format FOR TESTING. - METHODS parse_post_form_data FOR TESTING. - METHODS parse_fields_webgui FOR TESTING. - METHODS parse_fields_special_chars FOR TESTING. - - PRIVATE SECTION. - - CONSTANTS: BEGIN OF c_german_umlaut_as_hex, - lower_case_ae TYPE xstring VALUE 'C3A4', - lower_case_oe TYPE xstring VALUE 'C3B6', - lower_case_ue TYPE xstring VALUE 'C3BC', - END OF c_german_umlaut_as_hex. - - CLASS-DATA: BEGIN OF gs_german_umlaut_as_char, - lower_case_ae TYPE string, - lower_case_oe TYPE string, - lower_case_ue TYPE string, - END OF gs_german_umlaut_as_char. - - DATA mv_given_parse_string TYPE string. - DATA mt_parsed_fields TYPE tihttpnvp. - - METHODS _given_string_is - IMPORTING - iv_string TYPE string. - METHODS _when_fields_are_parsed_upper. - METHODS _when_fields_are_parsed. - METHODS _then_fields_should_be - IMPORTING - iv_index TYPE i - iv_name TYPE string - iv_value TYPE string. - METHODS _then_field_count_should_be - IMPORTING - iv_count TYPE i. - - CLASS-METHODS _hex_to_char - IMPORTING - iv_x TYPE xstring - RETURNING - VALUE(rv_s) TYPE string. - -ENDCLASS. - -CLASS zcl_abapgit_html_action_utils DEFINITION LOCAL FRIENDS ltcl_html_action_utils. - -CLASS ltcl_html_action_utils IMPLEMENTATION. - - METHOD class_constructor. - - gs_german_umlaut_as_char-lower_case_ae = _hex_to_char( c_german_umlaut_as_hex-lower_case_ae ). - gs_german_umlaut_as_char-lower_case_oe = _hex_to_char( c_german_umlaut_as_hex-lower_case_oe ). - gs_german_umlaut_as_char-lower_case_ue = _hex_to_char( c_german_umlaut_as_hex-lower_case_ue ). - - ENDMETHOD. - - METHOD parse_fields_simple_case. - - _given_string_is( `committer_name=Gustav Gans` ). - - _when_fields_are_parsed_upper( ). - - _then_fields_should_be( iv_index = 1 - iv_name = `COMMITTER_NAME` - iv_value = `Gustav Gans` ). - - ENDMETHOD. - - METHOD parse_fields_advanced_case. - - _given_string_is( `committer_name=Albert Schweitzer&` - && `committer_email=albert.schweitzer@googlemail.com&` - && `comment=dummy comment&` - && `body=Message body<><>with line break<>&` - && `author_name=Karl Klammer&` - && `author_email=karl@klammer.com` ). - - _when_fields_are_parsed_upper( ). - - _then_fields_should_be( iv_index = 1 - iv_name = `COMMITTER_NAME` - iv_value = `Albert Schweitzer` ). - - _then_fields_should_be( iv_index = 2 - iv_name = `COMMITTER_EMAIL` - iv_value = `albert.schweitzer@googlemail.com` ). - - _then_fields_should_be( iv_index = 3 - iv_name = `COMMENT` - iv_value = `dummy comment` ). - - _then_fields_should_be( iv_index = 4 - iv_name = `BODY` - iv_value = `Message body<><>with line break<>` ). - - _then_fields_should_be( iv_index = 5 - iv_name = `AUTHOR_NAME` - iv_value = `Karl Klammer` ). - - _then_fields_should_be( iv_index = 6 - iv_name = `AUTHOR_EMAIL` - iv_value = `karl@klammer.com` ). - - ENDMETHOD. - - METHOD parse_fields_unescape. - - " file status = '?', used in staging page - _given_string_is( '/SRC/ZFOOBAR.PROG.ABAP=%3F' ). - - _when_fields_are_parsed_upper( ). - _then_field_count_should_be( 1 ). - - _then_fields_should_be( - iv_index = 1 - iv_name = '/SRC/ZFOOBAR.PROG.ABAP' - iv_value = '?' ). - - ENDMETHOD. - - METHOD parse_fields_unescape_nbsp. - - " non-breaking space ( ) - _given_string_is( '/src/ztest_rfc.fugr.xml=%3F&/src/ztest_rfc' - && zcl_abapgit_html_action_utils=>gv_non_breaking_space - && zcl_abapgit_html_action_utils=>gv_non_breaking_space - && zcl_abapgit_html_action_utils=>gv_non_breaking_space - && 'rf.sush.xml=A' ). - - _when_fields_are_parsed( ). - _then_field_count_should_be( 2 ). - - _then_fields_should_be( - iv_index = 1 - iv_name = '/src/ztest_rfc.fugr.xml' - iv_value = '?' ). - - _then_fields_should_be( - iv_index = 2 - iv_name = '/src/ztest_rfc rf.sush.xml' - iv_value = 'A' ). - - ENDMETHOD. - - METHOD parse_fields_german_umlauts. - - DATA: lv_ae TYPE string, - lv_oe TYPE string, - lv_ue TYPE string, - lv_ae_oe_ue TYPE string. - - - lv_ae = gs_german_umlaut_as_char-lower_case_ae. - lv_oe = gs_german_umlaut_as_char-lower_case_oe. - lv_ue = gs_german_umlaut_as_char-lower_case_ue. - - lv_ae_oe_ue = lv_ae && lv_oe && lv_ue. - - _given_string_is( |committer_name=Christian G{ lv_ue }nter&| - && |committer_email=guenne@googlemail.com&| - && |comment={ lv_ae_oe_ue }&| - && |body=Message body<><>with line break<>and umlauts. { lv_ae_oe_ue }&| - && |author_name=Gerd Schr{ lv_oe }der&| - && |author_email=gerd@schroeder.com| ). - - _when_fields_are_parsed_upper( ). - - _then_fields_should_be( iv_index = 1 - iv_name = `COMMITTER_NAME` - iv_value = |Christian G{ lv_ue }nter| ). - - _then_fields_should_be( iv_index = 2 - iv_name = `COMMITTER_EMAIL` - iv_value = `guenne@googlemail.com` ). - - _then_fields_should_be( iv_index = 3 - iv_name = `COMMENT` - iv_value = lv_ae_oe_ue ). - - _then_fields_should_be( iv_index = 4 - iv_name = `BODY` - iv_value = |Message body<><>with line break<>and umlauts. { lv_ae_oe_ue }| ). - - _then_fields_should_be( iv_index = 5 - iv_name = `AUTHOR_NAME` - iv_value = |Gerd Schr{ lv_oe }der| ). - - _then_fields_should_be( iv_index = 6 - iv_name = `AUTHOR_EMAIL` - iv_value = `gerd@schroeder.com` ). - - ENDMETHOD. - - METHOD _given_string_is. - - mv_given_parse_string = iv_string. - - ENDMETHOD. - - METHOD _when_fields_are_parsed_upper. - - mt_parsed_fields = zcl_abapgit_html_action_utils=>parse_fields_upper_case_name( mv_given_parse_string ). - - ENDMETHOD. - - METHOD _when_fields_are_parsed. - - mt_parsed_fields = zcl_abapgit_html_action_utils=>parse_fields( mv_given_parse_string ). - - ENDMETHOD. - - METHOD _then_fields_should_be. - - FIELD-SYMBOLS: LIKE LINE OF mt_parsed_fields. - - READ TABLE mt_parsed_fields ASSIGNING INDEX iv_index. - - cl_abap_unit_assert=>assert_subrc( - exp = 0 - msg = |No parsed field found at index { iv_index }| ). - - cl_abap_unit_assert=>assert_equals( - act = -name - exp = iv_name - msg = |Name at index { iv_index } should be { iv_name }| ). - - cl_abap_unit_assert=>assert_equals( - act = -value - exp = iv_value - msg = |Value at index { iv_index } should be { iv_value }| ). - - ENDMETHOD. - - METHOD _then_field_count_should_be. - - cl_abap_unit_assert=>assert_equals( - act = lines( mt_parsed_fields ) - exp = iv_count - msg = |Field count { lines( mt_parsed_fields ) } should be { iv_count }| ). - - ENDMETHOD. - - METHOD _hex_to_char. - - DATA lo_conv TYPE REF TO cl_abap_conv_in_ce. - - lo_conv = cl_abap_conv_in_ce=>create( ). - lo_conv->convert( EXPORTING input = iv_x IMPORTING data = rv_s ). - - ENDMETHOD. - - METHOD parse_fields_wrong_format. - - _given_string_is( `some_query_string_without_param_structure` ). - _when_fields_are_parsed_upper( ). - _then_field_count_should_be( 0 ). - - _given_string_is( `some_query_string_without_param_structure&a=b` ). - _when_fields_are_parsed_upper( ). - _then_field_count_should_be( 1 ). - _then_fields_should_be( - iv_index = 1 - iv_name = 'A' - iv_value = 'b' ). - - ENDMETHOD. - - METHOD parse_post_form_data. - - DATA lt_post_data TYPE zif_abapgit_html_viewer=>ty_post_data. - DATA lv_line LIKE LINE OF lt_post_data. - DATA lv_long_name LIKE LINE OF lt_post_data. - DATA lv_size TYPE i. - - DESCRIBE FIELD lv_line LENGTH lv_size IN CHARACTER MODE. - lv_long_name = repeat( - val = 'x' - occ = lv_size - 4 ). - lv_line = 'a=b&' && lv_long_name. - - APPEND lv_line TO lt_post_data. - APPEND '=y' TO lt_post_data. - - mt_parsed_fields = zcl_abapgit_html_action_utils=>parse_post_form_data( lt_post_data ). - _then_field_count_should_be( 2 ). - _then_fields_should_be( - iv_index = 1 - iv_name = 'a' - iv_value = 'b' ). - _then_fields_should_be( - iv_index = 2 - iv_name = |{ lv_long_name }| - iv_value = 'y' ). - - mt_parsed_fields = zcl_abapgit_html_action_utils=>parse_post_form_data( - it_post_data = lt_post_data - iv_upper_cased = abap_true ). - _then_field_count_should_be( 2 ). - _then_fields_should_be( - iv_index = 1 - iv_name = 'A' - iv_value = 'b' ). - _then_fields_should_be( - iv_index = 2 - iv_name = |{ to_upper( lv_long_name ) }| - iv_value = 'y' ). - - ENDMETHOD. - - - METHOD parse_fields_webgui. - - _given_string_is( `KEY=000000000019&PATH=%2fsrc%2f&FILENAME=%2fnsp%2ftest_ddls_bug2.ddls.asddls` ). - _when_fields_are_parsed( ). - _then_field_count_should_be( 3 ). - - _then_fields_should_be( - iv_index = 1 - iv_name = 'KEY' - iv_value = '000000000019' ). - - _then_fields_should_be( - iv_index = 2 - iv_name = 'PATH' - iv_value = '/src/' ). - - _then_fields_should_be( - iv_index = 3 - iv_name = 'FILENAME' - iv_value = '/nsp/test_ddls_bug2.ddls.asddls' ). - - ENDMETHOD. - - METHOD parse_fields_special_chars. - - DATA lv_string TYPE string. - - " URL encoded data - lv_string = `TEST=!"#$%25%26'()*+,-./09:;<%3d>?@AZ[\]^_``az{|}~¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿`. - - _given_string_is( lv_string ). - _when_fields_are_parsed( ). - _then_field_count_should_be( 1 ). - - _then_fields_should_be( - iv_index = 1 - iv_name = 'TEST' - iv_value = `!"#$%&'()*+,-./09:;<=>?@AZ[\]^_``az{|}~¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿` ). - - ENDMETHOD. - -ENDCLASS. diff --git a/src/ui/lib/zcl_abapgit_html_action_utils.clas.xml b/src/ui/lib/zcl_abapgit_html_action_utils.clas.xml index 223fd4e04..9e8aa845b 100644 --- a/src/ui/lib/zcl_abapgit_html_action_utils.clas.xml +++ b/src/ui/lib/zcl_abapgit_html_action_utils.clas.xml @@ -10,7 +10,6 @@ X X X - X