症状
a) 您须要将文件从 SAP 应用程序服务器传输到仅反对 SFTP 协定的接管方。然而,SAP 应用程序服务器只能应用 HTTPS 协定发送文件。此外,您可能心愿在发送前对文件进行加密。

b) 您须要通过 HTTPS 将文件从近程服务器传输到 SAP 应用程序服务器。此外,您可能心愿在保留之前解密文件。

目前没有规范的程序或工具可用于文件加密、解密和传输。因而,您须要创立一个自定义程序。本阐明为您提供示例编码以反对您创立本人的程序。

请留神:PGP 加密不是SAP Employee Central Payroll 服务产品的一部分。起因如下: PGP 须要在利用服务器上安装额定的操作级软件,这在云环境中是不可能的

其余条款
SAP SuccessFactors Employee Central Payroll、SFTP 服务器、文件传输、加密、解密

起因和先决条件
在应用您的自定义程序之前,必须满足以下先决条件:

您有权创立报告程序、从应用程序服务器检索文件以及将它们上传到近程服务器。
在本地服务器上启动用于出站解决的程序的用户对本地文件具备 READ 受权:受权对象 S_DATASET、PROGRAM = SAPLSCMS_FILE、ACTVT = 33(读取)、FILENAME = <本地文件名,包含残缺门路>。
请留神:这并不一定意味着该用户能够显示文件内容。例如,如果您既未在程序中应用值帮忙,也未授予用户对象 S_TCODE 和 TCD = AL11 的受权,则他们将无奈从 UI 拜访文件内容。
在 FILE 事务中,您保护了传出和传入文件的逻辑门路和文件名。
在 SM59 事务中,您保护了一个类型为 G =“HTTP 连贯到内部服务器”的 RFC 指标,并将近程服务器作为指标主机。您已在“登录和平安”选项卡上保护了近程服务器的用户名和明码。两个零碎中必要的根本配置都已实现(例如,在零碎中建设可信连贯、受权等)。要创立到内部服务器的 HTTPS 连贯,Employee Central Payroll 零碎必须信赖服务器的证书。
要应用 SSL 连贯,您须要通过 STRUST 事务附加内部服务器的 CA 证书。示例报告应用默认客户端 PSE(SSL 客户端规范)连贯到近程服务器。
您已胜利执行 RFC 指标的连贯测试。
仅相干,如果您想应用加密性能:
在 STRUST 事务中,您保护了一个 PSE 并导入了您要发送的文件的最终收件人的证书。无关 STRUST 的更多信息,请参阅https://help.sap.com/viewer/2...
解决方案
SAP SuccessFactors 为客户提供对 SFTP 服务器的拜访。您能够先通过HTTPS从ABAP应用服务器向这个SFTP服务器发送文件,而后再通过SFTP协定从SFTP服务器传输给接管方。除了应用 SuccessFactors SFTP 服务器,您还能够将文件发送到任何其余通过 HTTPS 协定承受文件的近程服务器。

本笔记所附的示例代码显示,

a) 来自 ABAP 应用程序服务器的文件如何通过 HTTPS 检索、加密和发送到近程服务器

b) 如何通过 HTTPS 检索来自近程服务器的文件、解密并将其存储在 ABAP 应用程序服务器上。

示例程序只为 PSE 和收件人提供一对输出字段。在生产场景中,您不会应用雷同的 PSE 和收件人进行加密和解密。然而在您的施行和测试阶段,您可能想要查看是否正确调用了加密性能。为此,输出 PSE 所有者作为接收者(证书主题):只有这样,您能力在同一个 PSE 中同时领有用于加密的公钥和用于解密的私钥。

如果您对加密或解密有任何问题,请查看系统日志(SM21 事务)以获取无关问题本源的信息。

示例程序应用您在 SM59 事务中保护的 RFC 连贯。如果您将指标零碎的凭据存储在该 RFC 连贯中,您能够安顿程序并将其作为后台作业运行:凭据将从 SM59 配置中获取,并且在文件传输期间不会提醒您输出它们。

留神:在创立本人的程序时,请特地留神示例代码中以“@CUSTOMER”结尾的正文,因为您须要实现本人的逻辑。通过示例程序的流程逻辑,您能够看到如何调用性能(本地读/写、http 文件传输、解密/加密)。

留神:示例编码并非旨在高效应用,SAP 既不提供任何反对,也不对您基于此示例可能施行的任何内容负责。这尤其实用于平安问题:您有责任为您的编码增加平安性能,并相应地配置您的零碎(例如,爱护您的零碎免受病毒侵害)。

留神:示例程序中应用的 SSF_KRN_ENVELOPE 和 SSF_KRN_DEVELOPE 明码功能模块仅反对公钥明码规范 PKCS#7。非对称密钥必须是 RSA 或 ECDSA。反对的对称明码算法请参考 SAP note 2004653的对应局部。如果要显示所有反对的明码规范的列表,请启动事务 SE38,输出Program Name = SSF02并执行 (F8)。在选项局部,抉择SSF 格局字段的值帮忙以显示该列表。如果您应用SSFW_KRN_ENVELOPE和SSFW_KRN_DEVELOPE 功能模块,您能够应用这些规范中的任何一个加密/解密文件。

要在您本人的零碎中实现示例程序,请执行以下操作:

1.在SE38事务中,新建一个程序。例如,ZSAMPLE_CRYPT_TRANSFER_FILE 或抉择任何其余名称。

  1. 在编辑器中,抉择Utilities -> More Utilities -> Upload/Download 并将附件(ZSAMPLE_CRYPT_TRANSFER_FILE.txt)上传 到该程序中。
  2. 激活程序。
  3. 抉择Goto -> Text Elements为每个抉择参数和抉择屏幕的每个块定义文本。
    您会在抉择文本的选项卡上找到一些条目:这些条目是在程序激活期间依据抉择参数主动生成的,当初您只需填写文本。通过双击程序中块题目的文本符号 text-<xyz>
    为文本符号创立条目。适当的文本蕴含在示例编码中,作为每个抉择参数或块题目旁边的正文,您能够简略地将它们从那里复制到抉择文本或文本符号中。

提醒:您将在示例编码的开端找到抉择屏幕的定义。

  1. 激活文本。

sap 官网snote

*&---------------------------------------------------------------------*REPORT zsample_crypt_transfer_file.*&---------------------------------------------------------------------**&*& Sample report for*&  a) transferring a file from the application server*&     to an external file server via HTTP(S) protocol*&     Optionally, the file can be encrypted before sending*&  b) fetching a file from an external server via HTTP(S) and*&     saving it to the application server.*&     Optionally, the file can be decrypted before saving*&*& !!! Basic example only - coding needs to be adapted by customer!!!*&*& For adapting to customer specific needs, pay special attention*& to comments marked with '@CUSTOMER'*&*& !!! MESSAGE and WRITE statements              !!!*& !!! to be used only for testing in dialog mode!!!*& Define appropriate messages and write to application log*& in order to run the program in batch mode*&*&---------------------------------------------------------------------**& M O D I F I C A T I O N   L O G                                     **&---------------------------------------------------------------------**& Date         Author        Description                              **&---------------------------------------------------------------------**& yyyy-mm-dd   XXXXXXXXXX    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX**&*&---------------------------------------------------------------------** ======================================================================* Local classes* ======================================================================* ======================================================================* lcl_file:* Represents the file, provides basic operations like SAVE, and* cryptographic operations* =====================================================================CLASS lcl_file DEFINITION FINAL.  PUBLIC SECTION.    TYPES:      tty_line TYPE STANDARD TABLE OF ssfdata .    CONSTANTS gc_mode_orig TYPE c VALUE '1' ##NO_TEXT.    CONSTANTS gc_mode_decrypted TYPE c VALUE '2' ##NO_TEXT.    CONSTANTS gc_mode_encrypted TYPE c VALUE '3' ##NO_TEXT.    CONSTANTS gc_line_length TYPE i VALUE 255 ##NO_TEXT.    METHODS save      IMPORTING        !iv_pathname TYPE fileintern        !iv_mode     TYPE flag DEFAULT '2' .    METHODS encrypt      IMPORTING        !iv_pse       TYPE ssfappl        !iv_recipient TYPE certsubjct      RAISING        cx_crypto_error .    METHODS decrypt      IMPORTING        !iv_pse       TYPE ssfappl        !iv_recipient TYPE certsubjct      RAISING        cx_crypto_error .    METHODS create_from_xstring      IMPORTING        !iv_xstring  TYPE xstring        !iv_pathname TYPE string        !iv_bytes    TYPE i OPTIONAL .    METHODS load_from_applsrv      IMPORTING        !iv_pathname    TYPE fileintern        !iv_filename    TYPE string      RETURNING        VALUE(rv_subrc) TYPE i .    METHODS get_mimetype      RETURNING        VALUE(rv_mimetype) TYPE w3conttype .    METHODS get_xstring      IMPORTING        !iv_mode    TYPE c      EXPORTING        !ev_xstring TYPE xstring        !ev_length  TYPE i        !ev_subrc   TYPE sysubrc .  PRIVATE SECTION.    DATA: mv_extension        TYPE string,          mt_decrypted_line   TYPE tty_line,          mt_encrypted_line   TYPE saml2_pse_bin_data_t,          mt_source_line      TYPE tty_line,          mv_decrypted_length TYPE i,          mv_encrypted_length TYPE i,          mv_filename         TYPE string,          mv_source_length    TYPE i,          mv_mimetype         TYPE w3conttype.    METHODS set_name_and_type      IMPORTING        !iv_pathname TYPE string .ENDCLASS.CLASS lcl_file IMPLEMENTATION.  METHOD create_from_xstring.*      IMPORTING*        !iv_xstring  TYPE xstring*        !iv_pathname TYPE string*        !iv_bytes    TYPE i OPTIONAL .    " -------------------------------------------------------------    " Creates file content from given xstring and sets some    " instance attributes.    " Method can be used e.g. after retrieving a file via HTTP GET    " -------------------------------------------------------------    DATA:      lv_xstring TYPE xstring,      lv_line    TYPE ssfdata.    lv_xstring = iv_xstring.    IF iv_bytes IS INITIAL.      mv_source_length = xstrlen( lv_xstring ).    ELSE.      mv_source_length = iv_bytes.    ENDIF.    WHILE xstrlen( lv_xstring ) > 0.      lv_line = lv_xstring.      APPEND lv_line TO mt_source_line.      SHIFT lv_xstring LEFT BY gc_line_length PLACES IN BYTE MODE.    ENDWHILE.    set_name_and_type( iv_pathname ).  ENDMETHOD.  METHOD decrypt.*      IMPORTING*        !iv_pse       TYPE ssfappl*        !iv_recipient TYPE certsubjct*      RAISING*        cx_crypto_error .    " -----------------------------------------------------------------    " Decrypts the binary content of the original file and    " puts the result into mt_decrypted_line    " -----------------------------------------------------------------    FIELD-SYMBOLS:      <ls_source_line> TYPE ssfdata.    DATA:      ls_encrypted_line TYPE ssfbin,      lt_encrypted_line TYPE saml2_pse_bin_data_t,      lv_ssftoolkit     TYPE  ssftoolkit,      lv_str_format     TYPE  ssfform,      lv_str_profile    TYPE  ssfprof,      lv_crc            TYPE  ssfreturn,      lt_recipient      TYPE TABLE OF ssfinfo,      ls_recipient      TYPE ssfinfo.    " Before decrypting, we need to re-format the content:    " Decryption works with a structured line type, but    " the original content has a flat line type    LOOP AT mt_source_line ASSIGNING <ls_source_line>.      CLEAR ls_encrypted_line.      ls_encrypted_line-bindata = <ls_source_line>.      APPEND ls_encrypted_line TO lt_encrypted_line.    ENDLOOP.    CALL FUNCTION 'SSF_GET_PARAMETER'      EXPORTING        mandt       = sy-mandt        application = iv_pse      IMPORTING        ssftoolkit  = lv_ssftoolkit        str_format  = lv_str_format        str_profile = lv_str_profile      EXCEPTIONS        OTHERS      = 1.    IF sy-subrc <> 0.      WRITE: / 'SSF parameter read failed - see system log (SM21)'.      RAISE EXCEPTION TYPE cx_crypto_error.    ENDIF.    " function module needs a recipient list:    ls_recipient-id = iv_recipient.    ls_recipient-profile = lv_str_profile.    APPEND ls_recipient TO lt_recipient.    CALL FUNCTION 'SSF_KRN_DEVELOPE'      EXPORTING        ssftoolkit            = lv_ssftoolkit        str_format            = lv_str_format        ostr_enveloped_data_l = mv_source_length      IMPORTING        ostr_output_data_l    = mv_decrypted_length        crc                   = lv_crc      TABLES        ostr_enveloped_data   = lt_encrypted_line        recipient             = lt_recipient        ostr_output_data      = mt_decrypted_line      EXCEPTIONS        OTHERS                = 1.    IF sy-subrc <> 0 OR lv_crc <> 0 OR mt_decrypted_line IS INITIAL.      WRITE: / 'Decryption for file ', mv_filename, ' failed - see system log (SM21)'.      RAISE EXCEPTION TYPE cx_crypto_error.    ELSE.      WRITE: / 'File ', mv_filename, ' decrypted'.    ENDIF.  ENDMETHOD.  METHOD encrypt.*      IMPORTING*        !iv_pse       TYPE ssfappl*        !iv_recipient TYPE certsubjct*      RAISING*        cx_crypto_error .    " ---------------------------------------------------------------------------    " Encrypts the original binary file content using the given PSE and recipient,    " and puts the result into mt_encrypted_line    " ---------------------------------------------------------------------------    DATA:      lv_ssftoolkit       TYPE  ssftoolkit,      lv_str_format       TYPE  ssfform,      lv_str_pab          TYPE  ssfpab,      lv_str_pab_password TYPE  ssfpabpw,      lv_crc              TYPE  ssfreturn,      lt_recipient        TYPE TABLE OF ssfinfo,      ls_recipient        TYPE ssfinfo.    CALL FUNCTION 'SSF_GET_PARAMETER'      EXPORTING        mandt            = sy-mandt        application      = iv_pse      IMPORTING        ssftoolkit       = lv_ssftoolkit        str_format       = lv_str_format        str_pab          = lv_str_pab        str_pab_password = lv_str_pab_password      EXCEPTIONS        OTHERS           = 1.    IF sy-subrc <> 0.      WRITE: / 'SSF parameter read failed - see system log (SM21)'.      RAISE EXCEPTION TYPE cx_crypto_error.    ENDIF.    " put the specified recipient into the list:    ls_recipient-id = iv_recipient.    APPEND ls_recipient TO lt_recipient.    CALL FUNCTION 'SSF_KRN_ENVELOPE'      EXPORTING        ssftoolkit            = lv_ssftoolkit        str_format            = lv_str_format        ostr_input_data_l     = mv_source_length        str_pab               = lv_str_pab        str_pab_password      = lv_str_pab_password      IMPORTING        ostr_enveloped_data_l = mv_encrypted_length        crc                   = lv_crc      TABLES        ostr_input_data       = mt_source_line        recipient_list        = lt_recipient        ostr_enveloped_data   = mt_encrypted_line      EXCEPTIONS        OTHERS                = 1.    IF sy-subrc <> 0 OR lv_crc <> 0 OR mt_encrypted_line IS INITIAL.      WRITE: / 'File ', mv_filename, ': encryption failed - see system log (SM21)'.      RAISE EXCEPTION TYPE cx_crypto_error.    ELSE.      WRITE: / 'File ', mv_filename, ' encrypted'.    ENDIF.  ENDMETHOD.  METHOD get_mimetype.*      RETURNING*        VALUE(rv_mimetype) TYPE w3conttype .    rv_mimetype = mv_mimetype.  ENDMETHOD.  METHOD get_xstring.*      IMPORTING*        !iv_mode    TYPE c*      EXPORTING*        !ev_xstring TYPE xstring*        !ev_length  TYPE i*        !ev_subrc   TYPE sysubrc .    " -------------------------------------------------------------    " Returns the file content as xstring    " Depending on iv_mode, the original, decrypted or encrypted    " content is returned:    "  1 = original    "  2 = decrypted    "  3 = encrypted    " -------------------------------------------------------------    CONSTANTS lc_line_length TYPE i VALUE 255.    FIELD-SYMBOLS <fs_line> TYPE ssfbin.    DATA:      lt_line             TYPE tty_line,      lv_length           TYPE i,      lv_cumulated_length TYPE i.    CLEAR:       ev_xstring,       ev_length,       ev_subrc.    CASE iv_mode.      WHEN gc_mode_encrypted.        " Line type is structured -> requires special handling        lv_length = mv_encrypted_length.        LOOP AT mt_encrypted_line ASSIGNING <fs_line>.          " append current line at the correct position          CONCATENATE ev_xstring(lv_cumulated_length) <fs_line>-bindata INTO ev_xstring IN BYTE MODE.          lv_cumulated_length = lv_cumulated_length + lc_line_length.        ENDLOOP.        " set xstring to correct length (as provided by the encryption routine)        ev_xstring = ev_xstring(mv_encrypted_length).        ev_length = mv_encrypted_length.        RETURN.      WHEN gc_mode_orig.        lv_length = mv_source_length.        lt_line = mt_source_line.      WHEN gc_mode_decrypted.        lv_length = mv_decrypted_length.        lt_line = mt_decrypted_line.      WHEN OTHERS.        ev_subrc = 1.        RETURN.    ENDCASE.    " Original and decrypted lines both have unstructured line type    CONCATENATE LINES OF lt_line INTO ev_xstring IN BYTE MODE.    " set xstring to correct length:    " wrong length may cause errors in subsequent processing    ev_xstring = ev_xstring(lv_length).    ev_length = lv_length.  ENDMETHOD.  METHOD load_from_applsrv.*      IMPORTING*        !iv_pathname    TYPE fileintern*        !iv_filename     TYPE string*      RETURNING*        VALUE(rv_subrc) TYPE i .    " -------------------------------------------------------------    " Reads the file content from the specified location on the    " application server and sets some instance attributes    " -------------------------------------------------------------    DATA:      lv_filename(400) TYPE c,      lv_msg           TYPE string,      lv_flag          TYPE abap_bool,      lv_pathname      TYPE string,      lv_message       TYPE string.    CLEAR rv_subrc.    " ------------------------------------------------------------------    " !!! Programming guidelines !!!    " Prevent unauthorized file access by using    " logical paths and file names    " ------------------------------------------------------------------    CALL FUNCTION 'FILE_GET_NAME'      EXPORTING        logical_filename = iv_pathname        parameter_1      = iv_filename      IMPORTING        emergency_flag   = lv_flag        file_name        = lv_pathname      EXCEPTIONS        file_not_found   = 1        OTHERS           = 2.    rv_subrc = sy-subrc.    IF rv_subrc <> 0 OR lv_flag IS NOT INITIAL.      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4        INTO lv_message.      WRITE: / lv_message.      WRITE: / 'ERROR in FILE_GET_NAME - file will not be processed.'.      RETURN.    ENDIF.    CALL FUNCTION 'FILE_VALIDATE_NAME'      EXPORTING        logical_filename           = iv_pathname        parameter_1                = iv_filename      CHANGING        physical_filename          = lv_pathname      EXCEPTIONS        logical_filename_not_found = 1        validation_failed          = 2        OTHERS                     = 3.    rv_subrc = sy-subrc.    IF rv_subrc <> 0.      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4        INTO lv_message.      WRITE: / lv_message.      WRITE: / 'ERROR in FILE_VALIDATE_NAME - file will not be processed.'.      RETURN.    ENDIF.    " Read as BINARY in order to handle all mime types correctly    lv_filename = lv_pathname.    CALL FUNCTION 'SCMS_UPLOAD'      EXPORTING        filename = lv_filename " full name including path        binary   = 'X'        frontend = space      IMPORTING        filesize = mv_source_length      TABLES        data     = mt_source_line      EXCEPTIONS        error    = 1        OTHERS   = 2.    rv_subrc = sy-subrc.    IF rv_subrc <> 0.      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg.      WRITE: / lv_msg.      RETURN.    ENDIF.    set_name_and_type( lv_pathname ).  ENDMETHOD.  METHOD save.*      IMPORTING*        !iv_pathname TYPE fileintern*        !iv_mode     TYPE flag DEFAULT '2' .    " ----------------------------------------------------------------------    " Saves the file to the target folder on the application server.    " Depending on iv_mode, the original, decrypted or encrypted file    " shall be saved:    "  1 = original    "  2 = decrypted    "  3 = encrypted    " ----------------------------------------------------------------------    DATA:      lv_pathname  TYPE string,      lv_line      TYPE ssfdata,      lt_line      TYPE tty_line,      lv_length    TYPE i,      lv_cryptinfo TYPE string,      lv_message   TYPE string,      lv_flag      TYPE abap_bool.    FIELD-SYMBOLS:          <fs_line> TYPE ssfbin.    " ----------------------------------------------------------------------------    " !!! Programming guidelines !!!    " Prevent unauthorized file access by using    " logical paths and file names    " ----------------------------------------------------------------------------    CALL FUNCTION 'FILE_GET_NAME'      EXPORTING        logical_filename = iv_pathname        parameter_1      = mv_filename      IMPORTING        emergency_flag   = lv_flag        file_name        = lv_pathname      EXCEPTIONS        file_not_found   = 1        OTHERS           = 2.    IF sy-subrc <> 0 OR lv_flag IS NOT INITIAL.      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4        INTO lv_message.      WRITE: / lv_message.      WRITE: / 'ERROR in FILE_GET_NAME - file will not be stored.'.      RETURN.    ENDIF.    CALL FUNCTION 'FILE_VALIDATE_NAME'      EXPORTING        logical_filename           = iv_pathname        parameter_1                = mv_filename      CHANGING        physical_filename          = lv_pathname      EXCEPTIONS        logical_filename_not_found = 1        validation_failed          = 2        OTHERS                     = 3.    IF sy-subrc <> 0.      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4        INTO lv_message.      WRITE: / lv_message.      WRITE: / 'ERROR in FILE_VALIDATE_NAME - file will not be stored.'.      RETURN.    ENDIF.    " consolidate different data tables and formats    CASE iv_mode.      WHEN gc_mode_encrypted.        lv_cryptinfo = 'Encrypted file '.        " Line type is structured -> requires special handling        lv_length = mv_encrypted_length.        LOOP AT mt_encrypted_line ASSIGNING <fs_line>.          APPEND <fs_line>-bindata TO lt_line.        ENDLOOP.      WHEN gc_mode_orig.        lv_cryptinfo = 'Original file '.        lv_length = mv_source_length.        lt_line = mt_source_line.      WHEN gc_mode_decrypted.        lv_cryptinfo = 'Decrypted file '.        lv_length = mv_decrypted_length.        lt_line = mt_decrypted_line.      WHEN OTHERS.        RETURN.    ENDCASE.    IF lv_length > 0.      " Could be 0 e.g. if you are trying to save the decrypted version of      " a file that has never been decrypted.      OPEN DATASET lv_pathname FOR OUTPUT IN BINARY MODE.      LOOP AT lt_line INTO lv_line.        IF lv_length LT gc_line_length. "255.          TRANSFER lv_line(lv_length) TO lv_pathname.          EXIT. "from LOOP        ELSE.          TRANSFER lv_line TO lv_pathname.          lv_length = lv_length - gc_line_length.        ENDIF.      ENDLOOP.      CLOSE DATASET lv_pathname.      WRITE: / lv_cryptinfo, ' saved: ', lv_pathname.    ELSE.      WRITE: / lv_cryptinfo,  mv_filename, ' is empty - not saved'.    ENDIF.  ENDMETHOD.  METHOD set_name_and_type.*      IMPORTING*        !iv_pathname TYPE string .    " ----------------------------------------------    " Determines file name and mime type    " and stores them in instance attributes    " ----------------------------------------------    DATA:      lt_string    TYPE string_table,      lv_count     TYPE i,      lv_extension TYPE w3fileext.    CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH'      EXPORTING        full_name     = iv_pathname      IMPORTING        stripped_name = mv_filename      EXCEPTIONS        x_error       = 1        OTHERS        = 2.    IF sy-subrc <> 0.      WRITE: /'ERROR when splitting path.'.      RETURN.    ENDIF.    CLEAR lt_string.    SPLIT mv_filename AT '.' INTO TABLE lt_string.    DESCRIBE TABLE lt_string LINES lv_count.    IF lv_count GT 1.      READ TABLE lt_string INTO mv_extension INDEX lv_count.    ENDIF.    " string variable mv_extension cannot be passed into the function module    " SDOK_MIMETYPE_GET will set a default if there is no extension    lv_extension = mv_extension.    CALL FUNCTION 'SDOK_MIMETYPE_GET'      EXPORTING        extension = lv_extension      IMPORTING        mimetype  = mv_mimetype.  ENDMETHOD.ENDCLASS.* ======================================================================* lcl_file_http:* Utility class for http file transfer in both directions* ======================================================================CLASS lcl_file_http DEFINITION FINAL.  PUBLIC SECTION.    METHODS constructor      IMPORTING        !iv_rfc_dest TYPE rfcdest      RAISING        !cx_dest_http_abap_special      .    METHODS send      IMPORTING        !iv_target_folder TYPE string        !iv_file_name     TYPE string        !iv_content_type  TYPE string        !iv_content       TYPE xstring        !iv_bytes         TYPE i.    METHODS get      IMPORTING        !iv_source_path TYPE string      EXPORTING        !ev_content     TYPE xstring        !ev_bytes       TYPE i        !ev_subrc       TYPE sysubrc .  PRIVATE SECTION.    DATA mr_client TYPE REF TO if_http_client .    CONSTANTS mc_protocol TYPE string VALUE 'HTTP/1.1' ##NO_TEXT.    METHODS set_uri      IMPORTING        !iv_file_name     TYPE string        !iv_target_folder TYPE string      RETURNING        VALUE(rv_uri)     TYPE string .ENDCLASS.CLASS lcl_file_http IMPLEMENTATION.  METHOD constructor.*      IMPORTING*        !iv_rfc_dest TYPE rfcdest*      RAISING*        !cx_dest_http_abap_special    DATA: lv_rfc_dest  TYPE char32.    lv_rfc_dest = iv_rfc_dest.    " create http client for file transfer    CALL METHOD cl_http_client=>create_by_destination      EXPORTING        destination              = lv_rfc_dest      IMPORTING        client                   = mr_client      EXCEPTIONS        argument_not_found       = 1        destination_not_found    = 2        destination_no_authority = 3        plugin_not_active        = 4        internal_error           = 5        OTHERS                   = 6.    IF sy-subrc IS NOT INITIAL.      " not semantically fitting, but nothing better available in package SHTTP      RAISE EXCEPTION TYPE cx_dest_http_abap_special.    ENDIF.  ENDMETHOD.  METHOD get.*      IMPORTING*        !iv_source_path TYPE string*      EXPORTING*        !ev_content     TYPE xstring*        !ev_bytes       TYPE i*        !ev_subrc       TYPE sysubrc .    " ----------------------------------------------------------------    " Sets request attributes,    " gets file from the remote server,    " and handles errors    " ----------------------------------------------------------------    DATA: lv_xstring     TYPE xstring,          lv_path        TYPE string,          lr_http_entity TYPE REF TO if_http_entity,          lv_code        TYPE i,          lv_reason      TYPE string.    CLEAR ev_subrc.    CLEAR ev_bytes.    CLEAR ev_content.    CALL METHOD mr_client->refresh_request      EXCEPTIONS        http_action_failed = 1        OTHERS             = 2.    IF sy-subrc <> 0.      WRITE: / 'Could not refresh HTTP client - processing terminated.'.      RETURN.    ENDIF.    CONCATENATE '/' iv_source_path INTO lv_path.    CALL METHOD mr_client->request->set_header_field      EXPORTING        name  = if_http_header_fields_sap=>request_uri        value = mr_client->create_abs_url( path = lv_path ).    CALL METHOD mr_client->request->set_header_field      EXPORTING        name  = if_http_header_fields_sap=>request_method        value = 'GET'.    CALL METHOD mr_client->request->set_header_field      EXPORTING        name  = if_http_header_fields_sap=>server_protocol        value = mc_protocol.    CALL METHOD mr_client->send      EXPORTING        timeout = 0      EXCEPTIONS        OTHERS  = 0.    CALL METHOD mr_client->receive      EXCEPTIONS        http_communication_failure = 1        http_invalid_state         = 2        http_processing_failed     = 3        OTHERS                     = 4.    IF sy-subrc NE 0.      ev_subrc = sy-subrc.      WRITE:/ 'ERROR for file ',  iv_source_path, ': GET failed'.      WRITE:/ '    Reason: '.      CASE ev_subrc.        WHEN 1.          WRITE 'http communication failure'.        WHEN 2.          WRITE 'http invalid state'.        WHEN 3.          WRITE 'http processing failed'.        WHEN OTHERS.          WRITE 'not specified'.      ENDCASE.      RETURN.    ENDIF.    " Check the status of the response:    " Previous method calls may not have raised an exception    " even though the GET was not successful (e.g. if the file was not found)    CALL METHOD mr_client->response->get_status      IMPORTING        code   = lv_code        reason = lv_reason.    IF lv_code = '200'. " 200 = everything OK      lr_http_entity ?= mr_client->response.      " -----------------------------------------------------------------------      " @CUSTOMER:      " !!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!      " !!! Activate the virus scan when retrieving data from the remote server      " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!      " -----------------------------------------------------------------------      CALL METHOD lr_http_entity->get_data        EXPORTING          vscan_scan_always = if_http_entity=>co_content_check_always " !!! switch on virus scan !!!        RECEIVING          data              = lv_xstring.      IF lv_xstring IS INITIAL.        ev_subrc = 1.        WRITE: / 'ERROR: method GET_DATA returned an empty xstring for file ', iv_source_path.        RETURN.      ENDIF.      ev_content = lv_xstring.      ev_bytes = xstrlen( lv_xstring ).    ELSE.      WRITE:/ 'HTTP ERROR for file: ', iv_source_path, ',   Code: ',  lv_code, ',  Reason: ', lv_reason.      ev_subrc = 1.    ENDIF.  ENDMETHOD. "get  METHOD send.*      IMPORTING*        !iv_target_folder TYPE string*        !iv_file_name     TYPE string*        !iv_content_type  TYPE string*        !iv_content       TYPE xstring*        !iv_bytes         TYPE i.    " ----------------------------------------------------------------    " Sets request attributes,    " sends file to the remote server,    " and handles errors    " ----------------------------------------------------------------    DATA:      lv_code   TYPE i,      lv_reason TYPE string.    CALL METHOD mr_client->refresh_request      EXCEPTIONS        http_action_failed = 1        OTHERS             = 2.    IF sy-subrc <> 0.      WRITE: / 'Could not refresh HTTP client - processing terminated.'.      RETURN.    ENDIF.    CALL METHOD mr_client->request->set_header_field      EXPORTING        name  = if_http_header_fields_sap=>request_uri        value = set_uri( iv_target_folder = iv_target_folder                         iv_file_name     = iv_file_name ).    CALL METHOD mr_client->request->set_header_field      EXPORTING        name  = if_http_header_fields_sap=>request_method        value = 'PUT'.    CALL METHOD mr_client->request->set_header_field      EXPORTING        name  = if_http_header_fields_sap=>server_protocol        value = mc_protocol.    CALL METHOD mr_client->request->set_header_field      EXPORTING        name  = 'content-type'        value = iv_content_type.    CALL METHOD mr_client->request->set_data      EXPORTING        data   = iv_content        length = iv_bytes.    CALL METHOD mr_client->send      EXPORTING        timeout = 0.    CALL METHOD mr_client->receive      EXCEPTIONS        http_communication_failure = 1        http_invalid_state         = 2        http_processing_failed     = 3        OTHERS                     = 4.    IF sy-subrc NE 0.      WRITE:/ 'ERROR for file ',  iv_file_name, ': creation of remote file failed'.      WRITE:/ '    Reason: '.      CASE sy-subrc.        WHEN 1.          WRITE 'http communication failure'.        WHEN 2.          WRITE 'http invalid state'.        WHEN 3.          WRITE 'http processing failed'.        WHEN OTHERS.          WRITE 'not specified'.      ENDCASE.    ELSE.      CALL METHOD mr_client->response->get_status        IMPORTING          code   = lv_code          reason = lv_reason.      IF lv_code = '201'. " 201 = Created        WRITE: / 'File ', iv_file_name, ' sent.'.      ELSE.        WRITE:/ 'HTTP ERROR when sending file: ', iv_file_name, ',   Code: ',  lv_code, ',  Reason: ', lv_reason.      ENDIF.    ENDIF.  ENDMETHOD.* <SIGNATURE>---------------------------------------------------------------------------------------+* | Instance Protected Method LCL_FILE_http->SET_URI* +-------------------------------------------------------------------------------------------------+* | [--->] IV_FILE_NAME                   TYPE        STRING* | [--->] IV_TARGET_FOLDER               TYPE        STRING* | [<-()] RV_URI                         TYPE        STRING* +--------------------------------------------------------------------------------------</SIGNATURE>  METHOD set_uri.*      IMPORTING*        !iv_file_name     TYPE string*        !iv_target_folder TYPE string*      RETURNING*        VALUE(rv_uri)     TYPE string .    " Sets the full URI for the file in the target system    DATA lv_path TYPE string.    CONCATENATE '/' iv_target_folder '/' iv_file_name INTO lv_path.    CALL METHOD mr_client->create_abs_url      EXPORTING        path = lv_path      RECEIVING        url  = rv_uri.  ENDMETHOD.ENDCLASS.* ======================================================================* lcl_sample:* Handles the processing according to the parameters set* by the user on the selection screen of the report* ======================================================================CLASS lcl_sample DEFINITION FINAL.  PUBLIC SECTION.    METHODS main      IMPORTING        !iv_dest  TYPE rfcdest        !iv_out   TYPE abap_bool        !iv_multi TYPE abap_bool        !iv_lsrc  TYPE string        !iv_rsrc  TYPE string        !iv_rfold TYPE string        !iv_encr  TYPE abap_bool        !iv_decr  TYPE abap_bool        !iv_pse   TYPE ssfappl        !iv_rec   TYPE certsubjct      .    METHODS process_outbound      IMPORTING        !iv_multi TYPE abap_bool        !iv_lsrc  TYPE string        !iv_rfold TYPE string        !iv_encr  TYPE abap_bool        !iv_pse   TYPE ssfappl        !iv_rec   TYPE certsubjct      .    METHODS process_inbound      IMPORTING        !iv_rsrc TYPE string        !iv_decr TYPE abap_bool        !iv_pse  TYPE ssfappl        !iv_rec  TYPE certsubjct      .    METHODS get_file_list      IMPORTING        !iv_multi    TYPE abap_bool        !iv_lsrc     TYPE string      EXPORTING        !et_filename TYPE string_table      .  PRIVATE SECTION.****************************************************************************** @CUSTOMER:*** Use logical file names in order to prevent directory traversal.*** The user only has the possibility to select the file name, but not*** the directory on the application server.*** If you want to have some flexibility in the names of the actual files,*** customize your logical file names such that the name of the physical*** file is used as (part of) the logical file name.*** Otherwise, simply use hard-coded file names as well, and do not offer*** the user the possibility to enter them.****** Use transaction FILE to maintain logical paths and file names***************************************************************************    CONSTANTS: gc_logical_fname_inbound  TYPE fileintern VALUE 'ZSAMPLE_INBOUND',               gc_logical_fname_outbound TYPE fileintern VALUE 'ZSAMPLE_OUTBOUND'.    DATA: mo_file_http TYPE REF TO lcl_file_http.ENDCLASS.CLASS lcl_sample IMPLEMENTATION.  METHOD main.*      IMPORTING*        !iv_dest  TYPE rfcdest*        !iv_out   type abap_bool*        !iv_multi TYPE abap_bool*        !iv_lsrc  TYPE string*        !iv_rsrc  TYPE string*        !iv_rfold TYPE string*        !iv_encr  TYPE abap_bool*        !iv_decr  TYPE abap_bool*        !iv_pse   TYPE ssfappl*        !iv_rec   TYPE certsubjct*      .    TRY.        CREATE OBJECT mo_file_http          EXPORTING            iv_rfc_dest = iv_dest.      CATCH cx_dest_http_abap_special.        MESSAGE e016(pg) WITH 'Error in http client creation' ' - processing terminated'.        RETURN.    ENDTRY.    IF iv_out = abap_true.      CALL METHOD me->process_outbound        EXPORTING          iv_multi = iv_multi          iv_lsrc  = iv_lsrc          iv_rfold = iv_rfold          iv_encr  = iv_encr          iv_pse   = iv_pse          iv_rec   = iv_rec.    ELSE.      CALL METHOD me->process_inbound        EXPORTING          iv_rsrc = iv_rsrc          iv_decr = iv_decr          iv_pse  = iv_pse          iv_rec  = iv_rec.    ENDIF.    WRITE: / 'Processing finished.'.  ENDMETHOD.  METHOD process_outbound.*        !iv_multi TYPE abap_bool*        !iv_lsrc  TYPE string*        !iv_rfold TYPE string*        !iv_encr  TYPE abap_bool*        !iv_pse   TYPE ssfappl*        !iv_rec   TYPE certsubjct    " ---------------------------------------------------------    " Read files from the application server,    " encrypt them if requested,    " and send them to the remote server    " ---------------------------------------------------------    DATA:      lt_filename TYPE string_table,      lr_file     TYPE REF TO lcl_file,      lv_rc       TYPE sysubrc,      lv_xstring  TYPE xstring,      lv_bytes    TYPE i      .    FIELD-SYMBOLS:                   <lv_filename> TYPE string.    CALL METHOD get_file_list      EXPORTING        iv_multi    = iv_multi        iv_lsrc     = iv_lsrc      IMPORTING        et_filename = lt_filename. " file names without path    IF lt_filename IS INITIAL.      WRITE: / 'No files in local source directory - nothing to be sent'.      RETURN.    ENDIF.    LOOP AT lt_filename ASSIGNING <lv_filename>.      CREATE OBJECT lr_file.      " Load file from application server      " Logical file name is checked inside load_from_applsrv      CALL METHOD lr_file->load_from_applsrv        EXPORTING          iv_pathname = gc_logical_fname_outbound          iv_filename = <lv_filename>        RECEIVING          rv_subrc    = lv_rc.      IF lv_rc <> 0.        WRITE: / 'Could not load file ', <lv_filename>, ' - skipping it'.        CONTINUE.      ENDIF.      IF iv_encr = abap_true.        TRY.            CALL METHOD lr_file->encrypt              EXPORTING                iv_pse       = iv_pse                iv_recipient = iv_rec.          CATCH cx_crypto_error .            WRITE: / 'Error in encryption - ' ,  ' processing terminated'.            RETURN.        ENDTRY.        " use encrypted content for sending        CALL METHOD lr_file->get_xstring          EXPORTING            iv_mode    = lcl_file=>gc_mode_encrypted          IMPORTING            ev_xstring = lv_xstring            ev_length  = lv_bytes            ev_subrc   = lv_rc.      ELSE.        " use original content for sending        CALL METHOD lr_file->get_xstring          EXPORTING            iv_mode    = lcl_file=>gc_mode_orig          IMPORTING            ev_xstring = lv_xstring            ev_length  = lv_bytes            ev_subrc   = lv_rc.      ENDIF.      IF lv_rc <> 0.        CONTINUE.      ENDIF.      CALL METHOD mo_file_http->send        EXPORTING          iv_target_folder = iv_rfold          iv_file_name     = <lv_filename>          iv_content_type  = lr_file->get_mimetype( )          iv_content       = lv_xstring          iv_bytes         = lv_bytes.    ENDLOOP.  ENDMETHOD.  METHOD process_inbound.*      IMPORTING*        !iv_rsrc  TYPE string*        !iv_decr  TYPE abap_bool*        !iv_pse   TYPE ssfappl*        !iv_rec   TYPE certsubjct    " ---------------------------------------------------------    " Retrieve file from the remote server,    " decrypt it if requested,    " and store it on the application server    " ---------------------------------------------------------    DATA:      lr_file    TYPE REF TO lcl_file,      lv_content TYPE xstring,      lv_bytes   TYPE i,      lv_rc      TYPE sysubrc,      lv_mode    TYPE c.    CALL METHOD mo_file_http->get      EXPORTING        iv_source_path = iv_rsrc      IMPORTING        ev_content     = lv_content        ev_bytes       = lv_bytes        ev_subrc       = lv_rc.    IF lv_rc IS NOT INITIAL OR lv_bytes IS INITIAL.      WRITE: / 'Remote file could not be retrieved.'.      RETURN.    ENDIF.    CREATE OBJECT lr_file.    CALL METHOD lr_file->create_from_xstring      EXPORTING        iv_xstring  = lv_content        iv_pathname = iv_rsrc        iv_bytes    = lv_bytes.    IF iv_decr = abap_true.      TRY.          CALL METHOD lr_file->decrypt            EXPORTING              iv_pse       = iv_pse              iv_recipient = iv_rec.        CATCH cx_crypto_error .          WRITE: / 'Error in decryption - ' ,  ' file will not be saved'.          RETURN.      ENDTRY.      lv_mode = lcl_file=>gc_mode_decrypted.    ELSE.      lv_mode = lcl_file=>gc_mode_orig.    ENDIF.    CALL METHOD lr_file->save      EXPORTING        iv_pathname = gc_logical_fname_inbound        iv_mode     = lv_mode.  ENDMETHOD.  METHOD get_file_list.*      IMPORTING*        !iv_multi    TYPE abap_bool*        !iv_lsrc     TYPE string*      EXPORTING*        !et_filename TYPE string_table    " -----------------------------------------------------------------------    " Gets the list of file names (without path)    " for the files that are to be processed    " -----------------------------------------------------------------------    DATA:      lv_message  TYPE string,      lv_flag     TYPE abap_bool,      lv_dirname  TYPE epsdirnam,      lt_dir_list TYPE TABLE OF epsfili,      lv_filename TYPE string      .    FIELD-SYMBOLS:      <ls_dir_list>        TYPE epsfili      .    CLEAR et_filename.    IF iv_multi = abap_true.      " Get the names of all usable files in the logical path      " @CUSTOMER:      " This function call gives us the physical path to the      " logical file name - requires appropriate setup in      " transaction FILE      CALL FUNCTION 'FILE_GET_NAME'        EXPORTING          logical_filename = gc_logical_fname_outbound        IMPORTING          emergency_flag   = lv_flag          file_name        = lv_dirname  " physical path        EXCEPTIONS          file_not_found   = 1          OTHERS           = 2.      IF sy-subrc <> 0 OR lv_flag IS NOT INITIAL.        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4          INTO lv_message.        WRITE: / lv_message.        WRITE: / 'Logical path ', gc_logical_fname_outbound,  ' cannot be read - outbound processing cancelled.'.        RETURN.      ENDIF.      CALL FUNCTION 'EPS_GET_DIRECTORY_LISTING'        EXPORTING          dir_name               = lv_dirname        TABLES          dir_list               = lt_dir_list " file names without path, plus size        EXCEPTIONS          invalid_eps_subdir     = 1          sapgparam_failed       = 2          build_directory_failed = 3          no_authorization       = 4          read_directory_failed  = 5          too_many_read_errors   = 6          empty_directory_list   = 7          OTHERS                 = 8.      IF sy-subrc <> 0.        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno           WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4           INTO lv_message.        WRITE: / lv_message.        WRITE: / 'Physical path for  ', gc_logical_fname_outbound,  ' cannot be accessed - outbound processing cancelled.'.        RETURN.      ENDIF.      LOOP AT lt_dir_list ASSIGNING <ls_dir_list>.        CHECK <ls_dir_list>-rc = 0 AND              <ls_dir_list>-size > 0 AND              <ls_dir_list>-name(4) <> 'core'.        lv_filename = <ls_dir_list>-name.        APPEND lv_filename TO et_filename.      ENDLOOP.    ELSE.      " only one file (name entered by the user)      APPEND iv_lsrc TO et_filename.    ENDIF. " IF iv_multi = abap_true  ENDMETHOD.ENDCLASS.* ==================================================================* The report itself* ==================================================================" ------------------------------------------------------------------" GLOBAL VARIABLES" Mostly needed for handling screen fields (properties and content)" ------------------------------------------------------------------DATA: go_sample     TYPE REF TO lcl_sample ##NEEDED,      gv_program    TYPE sy-repid ##NEEDED,      gt_fieldvalue TYPE STANDARD TABLE OF rsselread ##NEEDED,      gs_fieldvalue TYPE rsselread ##NEEDED,      gv_encr       TYPE abap_bool ##NEEDED, " encrypt?      gv_decr       TYPE abap_bool ##NEEDED, " decrypt?      gv_rsrc       TYPE string ##NEEDED, " remote source file      gv_lsrc       TYPE string ##NEEDED, " local source file      gv_rfold      TYPE string ##NEEDED, " remote folder      gv_multi      TYPE abap_bool ##NEEDED. "all files from folder?************************************************************************ @CUSTOMER:*** Selections are mainly for testing purposes.*** Depending on your use case you may eliminate*** some - or even all - selection parameters*** For example, if you always send the same file*** to the same destination, you can hard-code all these parameters.*********************************************************************" ------------------------------------------------------------------" SELECTION SCREEN" ------------------------------------------------------------------" Settings for both inbound and outbound processingSELECTION-SCREEN: BEGIN OF BLOCK a01 WITH FRAME TITLE text-a01.              "General SettingsPARAMETERS: p_dest TYPE rfcdest MATCHCODE OBJECT esh_h_rfcdest_g OBLIGATORY. "RFC destination (as in SM59)SELECTION-SCREEN SKIP 1.SELECTION-SCREEN: BEGIN OF BLOCK a02 WITH FRAME TITLE text-a02.              "Encryption/DecryptionPARAMETERS: p_pse TYPE ssfappl MATCHCODE OBJECT f4strustssf.                 "SSF Application (PSE)PARAMETERS: p_rec TYPE  certsubjct.                                          "Recipient (Cert. Subject)SELECTION-SCREEN: END OF BLOCK a02.SELECTION-SCREEN: END OF BLOCK a01.SELECTION-SCREEN SKIP 1." Outbound processing onlyPARAMETERS: p_out RADIOBUTTON GROUP m1 DEFAULT 'X'.                          "Outbound Processing 出站解决SELECTION-SCREEN: BEGIN OF BLOCK b01 WITH FRAME.SELECTION-SCREEN: BEGIN OF BLOCK b02 WITH FRAME TITLE text-b02.              "Selection ModePARAMETERS: p_single RADIOBUTTON GROUP g1 DEFAULT 'X',                       "Single file 单个抉择文件            p_lsrc   TYPE string,                                            "Local Source File 本地源文件            p_multi  RADIOBUTTON GROUP g1.                                   "All Files from Folder 文件夹中的所有文件SELECTION-SCREEN: END OF BLOCK b02.PARAMETERS:  p_rfold TYPE string LOWER CASE,                                            "Remote Target Folder 远程目标文件夹  p_encr  AS CHECKBOX.                                                       "Encrypt before sending 发送前加密SELECTION-SCREEN: END OF BLOCK b01.SELECTION-SCREEN SKIP 1." Inbound processing onlyPARAMETERS: p_in RADIOBUTTON GROUP m1.                                       "Inbound Processing 入站解决SELECTION-SCREEN: BEGIN OF BLOCK c02 WITH FRAME.PARAMETERS: p_rsrc TYPE string LOWER CASE,                                   "Remote Source File 近程源文件            p_decr AS CHECKBOX.                                              "Decrypt before saving 保留前解密SELECTION-SCREEN: END OF BLOCK c02.INITIALIZATION.  " ----------------------------------------------------------  " @CUSTOMER:  " You must not use this sample coding 'as is'  " The program cannot be executed unless you make changes  " to the coding you copied from the sample  " ----------------------------------------------------------*“您不能应用“按原样”的示例编码”*“除非进行更改,否则无奈执行该程序*“复制到您从样本中复制的编码*" ---------------------------------------------  MESSAGE e016(pg) WITH '>>> This is only sample coding <<< ' '>>> Please adjust it to your needs <<<'." ------------------------------------------------------------------" SCREEN EVENTS" ------------------------------------------------------------------" ------------------------------------------------------------" Control the selection screen" ------------------------------------------------------------AT SELECTION-SCREEN OUTPUT.  " disable irrelevant fields, depending on outbound/inbound direction  PERFORM toggle_fields.AT SELECTION-SCREEN ON RADIOBUTTON GROUP m1.  " When user toggles between outbound and inbound:  " 1) get content of fields for both directions  " 2) disable fields for the direction that has not been selected  " 3) preserve existing field content such that it is still available  "    if the user toggles back*“当用户在出站和入站之间切换时:*“1)获取两个方向的字段内容*“2)禁用未抉择方向的字段*“3)保留现有字段内容,使其依然可用*“如果用户切换回  PERFORM get_field_content.  PERFORM toggle_fields.  PERFORM set_field_content.  " ----------------------------------------------------------  " Check input consistency  " ----------------------------------------------------------AT SELECTION-SCREEN.  IF p_out IS NOT INITIAL AND  p_rfold IS INITIAL.    MESSAGE e016(pg) WITH 'Please specify ' 'target folder for' 'outbound processing.'.  ENDIF.  IF p_out IS INITIAL AND p_rsrc IS INITIAL .    MESSAGE e016(pg) WITH 'Please specify' 'source file for' 'inbound processing.'.  ENDIF.  IF ( p_pse IS INITIAL OR p_rec IS INITIAL ) AND       ( ( p_out IS NOT INITIAL AND p_encr IS NOT INITIAL ) OR         ( p_out IS INITIAL AND p_decr IS NOT INITIAL )   ).    MESSAGE e016(pg) WITH 'Please specify' ' PSE and recipient for ' ' de-/encryption'.  ENDIF.  " ----------------------------------------------------------  " Trigger send/receive functionality  " ----------------------------------------------------------START-OF-SELECTION.  CREATE OBJECT go_sample.  CALL METHOD go_sample->main    EXPORTING      iv_dest  = p_dest      iv_out   = p_out      iv_multi = p_multi      iv_lsrc  = p_lsrc      iv_rsrc  = p_rsrc      iv_rfold = p_rfold      iv_encr  = p_encr      iv_decr  = p_decr      iv_pse   = p_pse      iv_rec   = p_rec.*&---------------------------------------------------------------------**&      Form  TOGGLE_FIELDS*&---------------------------------------------------------------------**       Enable or disable fields depending on selection of*       outbound / inbound processing*----------------------------------------------------------------------*FORM toggle_fields .  LOOP AT SCREEN.    IF p_out IS NOT INITIAL.      IF screen-name = 'P_RSRC' OR         screen-name = 'P_DECR'.        screen-input = 0.      ELSE.        IF screen-name = 'P_SINGLE' OR         screen-name = 'P_MULTI' OR         screen-name = 'P_RFOLD' OR         screen-name = 'P_ENCR'.          screen-input = 1.        ENDIF.        IF screen-name = 'P_LSRC'. "name of single file          IF p_single IS NOT INITIAL.            screen-input = 1.          ELSE.            screen-input = 0.          ENDIF.        ENDIF.      ENDIF.      MODIFY SCREEN.    ELSE.      IF screen-name = 'P_RSRC' OR         screen-name = 'P_DECR'.        screen-input = 1.      ELSEIF screen-name = 'P_SINGLE' OR         screen-name = 'P_MULTI' OR         screen-name = 'P_LSRC' OR         screen-name = 'P_RFOLD' OR         screen-name = 'P_ENCR'.        screen-input = 0.      ENDIF.      MODIFY SCREEN.    ENDIF.  ENDLOOP.ENDFORM.*&---------------------------------------------------------------------**&      Form  GET_FIELD_CONTENT*&---------------------------------------------------------------------**   Get field content from selection screen such that*   it can be preserved when user toggles between*   outbound and inbound*----------------------------------------------------------------------*FORM get_field_content .  gv_program = sy-repid.  CLEAR gt_fieldvalue.  " fields for outbound processing  gs_fieldvalue-kind = 'P'. "selection parameter  gs_fieldvalue-name = 'P_MULTI'.  APPEND gs_fieldvalue TO gt_fieldvalue.  gs_fieldvalue-name = 'P_LSRC'.  APPEND gs_fieldvalue TO gt_fieldvalue.  gs_fieldvalue-name = 'P_RFOLD'.  APPEND gs_fieldvalue TO gt_fieldvalue.  gs_fieldvalue-name = 'P_ENCR'.  APPEND gs_fieldvalue TO gt_fieldvalue.  " fields for inbound processing  gs_fieldvalue-name = 'P_RSRC'.  APPEND gs_fieldvalue TO gt_fieldvalue.  gs_fieldvalue-name = 'P_DECR'.  APPEND gs_fieldvalue TO gt_fieldvalue.  CALL FUNCTION 'RS_SELECTIONSCREEN_READ'    EXPORTING      program     = gv_program    TABLES      fieldvalues = gt_fieldvalue.  " outbound  READ TABLE gt_fieldvalue INTO gs_fieldvalue WITH KEY name = 'P_MULTI'.  IF sy-subrc = 0.    gv_multi = gs_fieldvalue-fieldvalue.  ENDIF.  READ TABLE gt_fieldvalue INTO gs_fieldvalue WITH KEY name = 'P_LSRC'.  IF sy-subrc = 0.    gv_lsrc = gs_fieldvalue-fieldvalue.  ENDIF.  READ TABLE gt_fieldvalue INTO gs_fieldvalue WITH KEY name = 'P_RFOLD'.  IF sy-subrc = 0.    gv_rfold = gs_fieldvalue-fieldvalue.  ENDIF.  READ TABLE gt_fieldvalue INTO gs_fieldvalue WITH KEY name = 'P_ENCR'.  IF sy-subrc = 0.    gv_encr = gs_fieldvalue-fieldvalue.  ENDIF.  " inbound  READ TABLE gt_fieldvalue INTO gs_fieldvalue WITH KEY name = 'P_RSRC'.  IF sy-subrc = 0.    gv_rsrc = gs_fieldvalue-fieldvalue.  ENDIF.  READ TABLE gt_fieldvalue INTO gs_fieldvalue WITH KEY name = 'P_DECR'.  IF sy-subrc = 0.    gv_decr = gs_fieldvalue-fieldvalue.  ENDIF.ENDFORM.*&---------------------------------------------------------------------**&      Form  SET_FIELD_CONTENT*&---------------------------------------------------------------------**       Set field content to previous values (after user*       has toggled between outbound and inbound)*----------------------------------------------------------------------*FORM set_field_content .  " outbound  p_rfold = gv_rfold.  p_multi = gv_multi.  p_lsrc = gv_lsrc.  p_encr = gv_encr.  " inbound  p_rsrc = gv_rsrc.  p_decr = gv_decr.ENDFORM.