From f000bfc2a329a22589038e77f0fc3fce05888e8a Mon Sep 17 00:00:00 2001 From: Lars Hvam Date: Wed, 15 Jul 2026 14:26:06 +0200 Subject: [PATCH 1/2] wip --- README.md | 37 +- abaplint.jsonc | 3 + docs/interactive-exec.md | 23 +- docs/sftp-sessions.md | 35 +- examples/zoassh_example_sftp.prog.abap | 18 +- scripts/check-public-api.test.mjs | 3 + src/zcl_oassh.clas.abap | 433 +++++++++++++++++------ src/zcl_oassh.clas.testclasses.abap | 42 +++ src/zcl_oassh_sftp.clas.abap | 35 +- src/zif_oassh_interactive_exec.intf.abap | 46 +++ src/zif_oassh_interactive_exec.intf.xml | 15 + src/zif_oassh_sftp_one_shot.intf.abap | 106 ++++++ src/zif_oassh_sftp_one_shot.intf.xml | 15 + src/zif_oassh_sftp_session.intf.abap | 89 +++++ src/zif_oassh_sftp_session.intf.xml | 15 + 15 files changed, 718 insertions(+), 197 deletions(-) create mode 100644 src/zif_oassh_interactive_exec.intf.abap create mode 100644 src/zif_oassh_interactive_exec.intf.xml create mode 100644 src/zif_oassh_sftp_one_shot.intf.abap create mode 100644 src/zif_oassh_sftp_one_shot.intf.xml create mode 100644 src/zif_oassh_sftp_session.intf.abap create mode 100644 src/zif_oassh_sftp_session.intf.xml diff --git a/README.md b/README.md index 21b807e..d5f4d44 100644 --- a/README.md +++ b/README.md @@ -150,14 +150,15 @@ host-verified connection for another session. ### SFTP -Called directly on a fresh connection, each SFTP method is one-shot: it opens -its own channel and subsystem, runs the single operation, and closes. Downloads -and uploads use `xstring` end to end: +Use `zif_oassh_sftp_one_shot` on a fresh connection for one operation. It opens +its own channel and subsystem, runs the operation, and closes the channel. +Downloads and uploads use `xstring` end to end: ```abap DATA lv_file TYPE xstring. +DATA li_sftp TYPE REF TO zif_oassh_sftp_one_shot. -lo_ssh = zcl_oassh=>connect( +li_sftp = zcl_oassh=>connect( iv_host = 'ssh.example.com' iv_port = '22' iv_user = 'deploy' @@ -165,13 +166,13 @@ lo_ssh = zcl_oassh=>connect( ii_host_verifier = lo_host_verifier ). TRY. - lv_file = lo_ssh->sftp_download( + lv_file = li_sftp->sftp_download( iv_path = '/incoming/data.bin' iv_timeout_seconds = 60 ). CLEANUP. - lo_ssh->close( ). + li_sftp->close( ). ENDTRY. -lo_ssh->close( ). +li_sftp->close( ). ``` The public SFTP methods are: @@ -190,24 +191,26 @@ file. #### Multi-operation SFTP sessions -To run several SFTP operations over a single authenticated connection, call -`sftp_open` first. It performs the channel, subsystem, and INIT/VERSION +To run several SFTP operations over a single authenticated connection, use +`zif_oassh_sftp_session` and call `sftp_open` first. It performs the channel, +subsystem, and INIT/VERSION handshake once; the same `sftp_*` methods then run inside that session until `sftp_close`. This avoids repeating the full SSH handshake — and, on APC, the one-byte-per-frame cost of every handshake — for each operation: ```abap -lo_ssh = zcl_oassh=>connect( ... ). +DATA li_sftp TYPE REF TO zif_oassh_sftp_session. +li_sftp = zcl_oassh=>connect( ... ). TRY. - lo_ssh->sftp_open( ). - lt_names = lo_ssh->sftp_list( '/incoming' ). - lv_file = lo_ssh->sftp_download( '/incoming/data.bin' ). - ls_attrs = lo_ssh->sftp_stat( '/incoming/data.bin' ). - lo_ssh->sftp_close( ). + li_sftp->sftp_open( ). + lt_names = li_sftp->sftp_list( '/incoming' ). + lv_file = li_sftp->sftp_download( '/incoming/data.bin' ). + ls_attrs = li_sftp->sftp_stat( '/incoming/data.bin' ). + li_sftp->sftp_close( ). CLEANUP. - lo_ssh->close( ). + li_sftp->close( ). ENDTRY. -lo_ssh->close( ). +li_sftp->close( ). ``` One SFTP operation runs at a time, and the session is not reused across diff --git a/abaplint.jsonc b/abaplint.jsonc index d069487..52b005d 100644 --- a/abaplint.jsonc +++ b/abaplint.jsonc @@ -38,6 +38,9 @@ "begin_end_names": true, "begin_single_include": true, "call_transaction_authority_check": true, + "add_test_attributes": true, + "aff_and_xml": true, + "align_pseudo_comments": true, "cds_parser_error": true, "chain_mainly_declarations": true, "check_abstract": true, diff --git a/docs/interactive-exec.md b/docs/interactive-exec.md index 0a1025f..26eec1c 100644 --- a/docs/interactive-exec.md +++ b/docs/interactive-exec.md @@ -7,8 +7,8 @@ response, decide, and write the next request while the command keeps running. The canonical example is `git-upload-pack`, which GitHub exposes to deploy keys: ref advertisement down, `want`/`done` up, packfile down. -The interactive exec API keeps the session channel open and hands the -byte streams to the caller: +The `zif_oassh_interactive_exec` interface keeps the session channel open and +hands the byte streams to the caller: | Method | Purpose | | --- | --- | @@ -31,18 +31,20 @@ command's output stream has ended (the peer sent `CHANNEL_EOF` or the connection closed). Callers therefore loop: ```abap -DATA(lo_ssh) = zcl_oassh=>connect( +DATA li_exec TYPE REF TO zif_oassh_interactive_exec. + +li_exec = zcl_oassh=>connect( iv_host = 'github.com' iv_port = '22' iv_user = 'git' iv_private_seed = lv_ed25519_seed " the deploy key ii_host_verifier = li_verifier ). -lo_ssh->exec_open( |git-upload-pack 'owner/repo.git'| ). +li_exec->exec_open( |git-upload-pack 'owner/repo.git'| ). DATA(lv_advertisement) = VALUE xstring( ). -WHILE lo_ssh->exec_is_closed( ) = abap_false. - DATA(lv_chunk) = lo_ssh->exec_read( ). +WHILE li_exec->exec_is_closed( ) = abap_false. + DATA(lv_chunk) = li_exec->exec_read( ). IF lv_chunk IS INITIAL. EXIT. " timeout: decide whether the protocol layer has a complete unit ENDIF. @@ -50,9 +52,10 @@ WHILE lo_ssh->exec_is_closed( ) = abap_false. " ... hand to a pkt-line parser, stop when it has the full advertisement ENDWHILE. -lo_ssh->exec_write( lv_want_request ). " pkt-lines: want, deepen, flush, done +li_exec->exec_write( lv_want_request ). " pkt-lines: want, deepen, flush, done " ... read the packfile with the same exec_read loop -lo_ssh->exec_close( ). +li_exec->exec_close( ). +li_exec->close( ). ``` ## Flow control @@ -63,8 +66,8 @@ that do not fit are queued and sent automatically when the server's `exec_eof( )` refuses to half-close while stdin is still queued, because those bytes could never be delivered afterwards. -Like every other operation on `zcl_oassh`, an interactive exec is the one -operation of its connection object: `exec_open( )` on a connection that +Like every other workflow, an interactive exec is the one operation of its +connection object: `exec_open( )` on a connection that already ran an operation raises the usual typed error. ## Scope diff --git a/docs/sftp-sessions.md b/docs/sftp-sessions.md index 5db604e..21d23af 100644 --- a/docs/sftp-sessions.md +++ b/docs/sftp-sessions.md @@ -1,8 +1,8 @@ # Multi-operation SFTP sessions -Each `sftp_*` method on `zcl_oassh` is one-shot by default: it authenticates, -opens a session channel, starts the `sftp` subsystem, runs a single operation, -and closes the channel. Every operation therefore pays for a full SSH handshake +Each method on `zif_oassh_sftp_one_shot` authenticates, opens a session channel, +starts the `sftp` subsystem, runs a single operation, and closes the channel. +Every operation therefore pays for a full SSH handshake and a fresh subsystem — expensive when a caller needs several operations in a row, and especially so on APC, where each handshake is exchanged one byte per frame. @@ -12,12 +12,12 @@ the channel, subsystem, and INIT/VERSION handshake once; the same `sftp_*` methods then run inside that single subsystem channel until `sftp_close`. ```abap -DATA lo_ssh TYPE REF TO zcl_oassh. -DATA lt_names TYPE zcl_oassh_sftp=>ty_names. +DATA li_sftp TYPE REF TO zif_oassh_sftp_session. +DATA lt_names TYPE zif_oassh_sftp_session=>ty_names. DATA lv_data TYPE xstring. -DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs. +DATA ls_attrs TYPE zif_oassh_sftp_session=>ty_attrs. -lo_ssh = zcl_oassh=>connect( +li_sftp = zcl_oassh=>connect( iv_host = 'ssh.example.com' iv_port = '22' iv_user = 'deploy' @@ -25,18 +25,18 @@ lo_ssh = zcl_oassh=>connect( ii_host_verifier = lo_host_verifier ). TRY. - lo_ssh->sftp_open( ). " channel + subsystem + INIT/VERSION - lt_names = lo_ssh->sftp_list( '/incoming' ). - lv_data = lo_ssh->sftp_download( '/incoming/data.bin' ). - ls_attrs = lo_ssh->sftp_stat( '/incoming/data.bin' ). - lo_ssh->sftp_rename( + li_sftp->sftp_open( ). " channel + subsystem + INIT/VERSION + lt_names = li_sftp->sftp_list( '/incoming' ). + lv_data = li_sftp->sftp_download( '/incoming/data.bin' ). + ls_attrs = li_sftp->sftp_stat( '/incoming/data.bin' ). + li_sftp->sftp_rename( iv_old_path = '/incoming/data.bin' iv_new_path = '/incoming/data.bin.done' ). - lo_ssh->sftp_close( ). " channel close handshake + li_sftp->sftp_close( ). " channel close handshake CLEANUP. - lo_ssh->close( ). + li_sftp->close( ). ENDTRY. -lo_ssh->close( ). +li_sftp->close( ). ``` ## API @@ -52,8 +52,9 @@ lo_ssh->close( ). usual typed error, and a session is never reused across those other kinds or a second channel. -Without `sftp_open`, every `sftp_*` method behaves exactly as before — one-shot, -one connection per operation — so existing callers are unaffected. +Use `zif_oassh_sftp_one_shot` when no reusable session is needed. The concrete +SFTP methods on `zcl_oassh` are implementation details; callers select one of +the two SFTP interfaces explicitly. ## Semantics diff --git a/examples/zoassh_example_sftp.prog.abap b/examples/zoassh_example_sftp.prog.abap index 86ac392..1396a6c 100644 --- a/examples/zoassh_example_sftp.prog.abap +++ b/examples/zoassh_example_sftp.prog.abap @@ -44,8 +44,8 @@ START-OF-SELECTION. FORM run. DATA lo_host_verifier TYPE REF TO zif_oassh_host_verifier. - DATA lo_ssh TYPE REF TO zcl_oassh. - DATA lt_names TYPE zcl_oassh_sftp=>ty_names. + DATA li_sftp TYPE REF TO zif_oassh_sftp_session. + DATA lt_names TYPE zif_oassh_sftp_session=>ty_names. DATA lv_filename TYPE string. DATA lv_data TYPE xstring. DATA lv_preview TYPE string. @@ -59,30 +59,30 @@ FORM run. TRY. * ii_random is optional on SAP: zcl_oassh defaults to zcl_oassh_random_secure, * which draws from the kernel-backed secure random source. - lo_ssh = zcl_oassh=>connect( + li_sftp = zcl_oassh=>connect( iv_host = p_host iv_port = p_port iv_user = p_user iv_password = p_pass ii_host_verifier = lo_host_verifier ). TRY. - lo_ssh->sftp_open( p_tmout ). + li_sftp->sftp_open( p_tmout ). * --- list a directory ----------------------------------------------------- - lt_names = lo_ssh->sftp_list( + lt_names = li_sftp->sftp_list( iv_path = p_dir iv_timeout_seconds = p_tmout ). * --- download a file ------------------------------------------------------ - lv_data = lo_ssh->sftp_download( + lv_data = li_sftp->sftp_download( iv_path = p_file iv_timeout_seconds = p_tmout ). - lo_ssh->sftp_close( p_tmout ). + li_sftp->sftp_close( p_tmout ). CLEANUP. - lo_ssh->close( ). + li_sftp->close( ). ENDTRY. - lo_ssh->close( ). + li_sftp->close( ). WRITE: / 'listing of', p_dir. SKIP. diff --git a/scripts/check-public-api.test.mjs b/scripts/check-public-api.test.mjs index fd3d3ae..530255b 100644 --- a/scripts/check-public-api.test.mjs +++ b/scripts/check-public-api.test.mjs @@ -4,6 +4,9 @@ import test from "node:test"; const publicSources = [ "../src/zcl_oassh.clas.abap", + "../src/zif_oassh_interactive_exec.intf.abap", + "../src/zif_oassh_sftp_one_shot.intf.abap", + "../src/zif_oassh_sftp_session.intf.abap", "../src/platform/zif_oassh_socket.intf.abap", ]; diff --git a/src/zcl_oassh.clas.abap b/src/zcl_oassh.clas.abap index 772c891..8fe4cc4 100644 --- a/src/zcl_oassh.clas.abap +++ b/src/zcl_oassh.clas.abap @@ -4,6 +4,10 @@ CLASS zcl_oassh DEFINITION PUBLIC SECTION. + INTERFACES zif_oassh_interactive_exec. + INTERFACES zif_oassh_sftp_one_shot. + INTERFACES zif_oassh_sftp_session. + CLASS-METHODS connect IMPORTING iv_host TYPE string @@ -27,29 +31,6 @@ CLASS zcl_oassh DEFINITION VALUE(rv_output) TYPE string RAISING zcx_oassh_error. -* Multi-operation SFTP session: sftp_open( ) performs the channel, subsystem -* and INIT/VERSION handshake once, then the sftp_* methods below run inside -* that single session until sftp_close( ). Without sftp_open( ) each sftp_* -* method is one-shot (its own connection lifecycle), exactly as before. -* See docs/sftp-sessions.md. - METHODS sftp_open - IMPORTING - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING - zcx_oassh_error. - METHODS sftp_close - IMPORTING - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING - zcx_oassh_error. - METHODS sftp_download - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RETURNING - VALUE(rv_data) TYPE xstring - RAISING - zcx_oassh_error. METHODS shell IMPORTING iv_input TYPE xstring @@ -61,97 +42,6 @@ CLASS zcl_oassh DEFINITION VALUE(rv_output) TYPE xstring RAISING zcx_oassh_error. -* Interactive exec: exec_open starts a command and returns while the channel -* stays open, so the caller can interleave binary stdin and stdout, for -* example to speak a request/response protocol such as git-upload-pack. -* The conversation ends with exec_close. See docs/interactive-exec.md. - METHODS exec_open - IMPORTING - iv_command TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING - zcx_oassh_error. - METHODS exec_write - IMPORTING - iv_data TYPE xstring - RAISING - zcx_oassh_error. - METHODS exec_read - IMPORTING - iv_timeout_seconds TYPE i DEFAULT 300 - RETURNING - VALUE(rv_data) TYPE xstring - RAISING - zcx_oassh_error. - METHODS exec_eof - RAISING - zcx_oassh_error. - METHODS exec_close - IMPORTING - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING - zcx_oassh_error. - METHODS exec_is_closed - RETURNING - VALUE(rv_closed) TYPE abap_bool. - METHODS sftp_upload - IMPORTING - iv_path TYPE string - iv_data TYPE xstring - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING - zcx_oassh_error. - METHODS sftp_stat - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RETURNING - VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs - RAISING - zcx_oassh_error. - METHODS sftp_lstat - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RETURNING - VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs - RAISING - zcx_oassh_error. - METHODS sftp_list - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RETURNING - VALUE(rt_names) TYPE zcl_oassh_sftp=>ty_names - RAISING - zcx_oassh_error. - METHODS sftp_mkdir - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING zcx_oassh_error. - METHODS sftp_rmdir - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING zcx_oassh_error. - METHODS sftp_remove - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING zcx_oassh_error. - METHODS sftp_rename - IMPORTING - iv_old_path TYPE string - iv_new_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RAISING zcx_oassh_error. - METHODS sftp_realpath - IMPORTING - iv_path TYPE string - iv_timeout_seconds TYPE i DEFAULT 300 - RETURNING VALUE(rs_name) TYPE zcl_oassh_sftp=>ty_name - RAISING zcx_oassh_error. METHODS get_stderr RETURNING VALUE(rv_output) TYPE string. @@ -238,6 +128,95 @@ CLASS zcl_oassh DEFINITION DATA mv_disconnected TYPE abap_bool. DATA mv_disconnect_reason TYPE i. +* Concrete implementations shared by the workflow interfaces. + METHODS exec_open + IMPORTING + iv_command TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS exec_write + IMPORTING iv_data TYPE xstring + RAISING zcx_oassh_error. + METHODS exec_read + IMPORTING iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rv_data) TYPE xstring + RAISING zcx_oassh_error. + METHODS exec_eof RAISING zcx_oassh_error. + METHODS exec_close + IMPORTING iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS exec_is_closed + RETURNING VALUE(rv_closed) TYPE abap_bool. + METHODS sftp_open + IMPORTING iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_close + IMPORTING iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_download + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rv_data) TYPE xstring + RAISING zcx_oassh_error. + METHODS sftp_upload + IMPORTING + iv_path TYPE string + iv_data TYPE xstring + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_stat + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs + RAISING zcx_oassh_error. + METHODS sftp_lstat + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs + RAISING zcx_oassh_error. + METHODS sftp_list + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rt_names) TYPE zcl_oassh_sftp=>ty_names + RAISING zcx_oassh_error. + METHODS sftp_mkdir + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_rmdir + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_remove + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_rename + IMPORTING + iv_old_path TYPE string + iv_new_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_realpath + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rs_name) TYPE zcl_oassh_sftp=>ty_name + RAISING zcx_oassh_error. + METHODS handle_transport_message IMPORTING iv_payload TYPE xstring @@ -356,6 +335,232 @@ ENDCLASS. CLASS zcl_oassh IMPLEMENTATION. + METHOD zif_oassh_interactive_exec~exec_open. + exec_open( + iv_command = iv_command + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~exec_write. + exec_write( iv_data ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~exec_read. + rv_data = exec_read( iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~exec_eof. + exec_eof( ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~exec_close. + exec_close( iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~exec_is_closed. + rv_closed = exec_is_closed( ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~get_stderr. + rv_output = get_stderr( ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~get_exit_status. + rv_status = get_exit_status( ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~get_disconnect_reason. + rv_reason = get_disconnect_reason( ). + ENDMETHOD. + + + METHOD zif_oassh_interactive_exec~close. + close( ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_download. + rv_data = sftp_download( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_upload. + sftp_upload( + iv_path = iv_path + iv_data = iv_data + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_stat. + rs_attrs = sftp_stat( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_lstat. + rs_attrs = sftp_lstat( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_list. + rt_names = sftp_list( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_mkdir. + sftp_mkdir( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_rmdir. + sftp_rmdir( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_remove. + sftp_remove( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_rename. + sftp_rename( + iv_old_path = iv_old_path + iv_new_path = iv_new_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~sftp_realpath. + rs_name = sftp_realpath( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~get_disconnect_reason. + rv_reason = get_disconnect_reason( ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_one_shot~close. + close( ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_open. + sftp_open( iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_close. + sftp_close( iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_download. + rv_data = sftp_download( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_upload. + sftp_upload( + iv_path = iv_path + iv_data = iv_data + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_stat. + rs_attrs = sftp_stat( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_lstat. + rs_attrs = sftp_lstat( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_list. + rt_names = sftp_list( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_mkdir. + sftp_mkdir( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_rmdir. + sftp_rmdir( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_remove. + sftp_remove( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_rename. + sftp_rename( + iv_old_path = iv_old_path + iv_new_path = iv_new_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~sftp_realpath. + rs_name = sftp_realpath( + iv_path = iv_path + iv_timeout_seconds = iv_timeout_seconds ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~get_disconnect_reason. + rv_reason = get_disconnect_reason( ). + ENDMETHOD. + + + METHOD zif_oassh_sftp_session~close. + close( ). + ENDMETHOD. + + METHOD connect. DATA li_socket TYPE REF TO zif_oassh_socket. diff --git a/src/zcl_oassh.clas.testclasses.abap b/src/zcl_oassh.clas.testclasses.abap index 8cf79c2..a6edc2f 100644 --- a/src/zcl_oassh.clas.testclasses.abap +++ b/src/zcl_oassh.clas.testclasses.abap @@ -33,6 +33,7 @@ CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL. METHODS exec_stream_guards FOR TESTING RAISING cx_static_check. METHODS sftp_session_dispatch FOR TESTING RAISING cx_static_check. METHODS sftp_session_guards FOR TESTING RAISING cx_static_check. + METHODS workflow_interfaces FOR TESTING RAISING cx_static_check. METHODS sftp_api_state FOR TESTING RAISING cx_static_check. METHODS empty_command_state FOR TESTING RAISING cx_static_check. METHODS execute_early_failure FOR TESTING RAISING cx_static_check. @@ -99,6 +100,47 @@ ENDCLASS. CLASS ltcl_test IMPLEMENTATION. + METHOD workflow_interfaces. + DATA li_exec TYPE REF TO zif_oassh_interactive_exec. + DATA li_one_shot TYPE REF TO zif_oassh_sftp_one_shot. + DATA li_session TYPE REF TO zif_oassh_sftp_session. + DATA lx_error TYPE REF TO zcx_oassh_error. + + li_exec = build_ssh( ). + TRY. + li_exec->exec_open( + iv_command = 'true' + iv_timeout_seconds = 0 ). + cl_abap_unit_assert=>fail( 'interactive interface did not delegate' ). + CATCH zcx_oassh_error INTO lx_error. + cl_abap_unit_assert=>assert_equals( + act = lx_error->if_t100_message~t100key-msgno + exp = '001' ). + ENDTRY. + + li_one_shot = build_ssh( ). + TRY. + li_one_shot->sftp_download( + iv_path = '/tmp/file' + iv_timeout_seconds = 0 ). + cl_abap_unit_assert=>fail( 'one-shot interface did not delegate' ). + CATCH zcx_oassh_error INTO lx_error. + cl_abap_unit_assert=>assert_equals( + act = lx_error->if_t100_message~t100key-msgno + exp = '001' ). + ENDTRY. + + li_session = build_ssh( ). + TRY. + li_session->sftp_open( 0 ). + cl_abap_unit_assert=>fail( 'session interface did not delegate' ). + CATCH zcx_oassh_error INTO lx_error. + cl_abap_unit_assert=>assert_equals( + act = lx_error->if_t100_message~t100key-msgno + exp = '001' ). + ENDTRY. + ENDMETHOD. + METHOD close_clears_secrets. DATA lo_ssh TYPE REF TO zcl_oassh. lo_ssh = build_ssh( ). diff --git a/src/zcl_oassh_sftp.clas.abap b/src/zcl_oassh_sftp.clas.abap index 3f4d19d..92fdae7 100644 --- a/src/zcl_oassh_sftp.clas.abap +++ b/src/zcl_oassh_sftp.clas.abap @@ -4,36 +4,11 @@ CLASS zcl_oassh_sftp DEFINITION CREATE PUBLIC. PUBLIC SECTION. - TYPES ty_uint32 TYPE x LENGTH 4. - TYPES ty_uint64 TYPE x LENGTH 8. - TYPES: - BEGIN OF ty_extension, - extension_type TYPE xstring, - extension_data TYPE xstring, - END OF ty_extension. - TYPES ty_extensions TYPE STANDARD TABLE OF ty_extension WITH EMPTY KEY. - TYPES: - BEGIN OF ty_attrs, - flags TYPE ty_uint32, - has_size TYPE abap_bool, - size TYPE ty_uint64, - has_uid_gid TYPE abap_bool, - uid TYPE ty_uint32, - gid TYPE ty_uint32, - has_permissions TYPE abap_bool, - permissions TYPE ty_uint32, - has_acmodtime TYPE abap_bool, - atime TYPE ty_uint32, - mtime TYPE ty_uint32, - extensions TYPE ty_extensions, - END OF ty_attrs. - TYPES: - BEGIN OF ty_name, - filename TYPE xstring, - longname TYPE xstring, - attrs TYPE ty_attrs, - END OF ty_name. - TYPES ty_names TYPE STANDARD TABLE OF ty_name WITH EMPTY KEY. + TYPES ty_uint32 TYPE zif_oassh_sftp_one_shot=>ty_uint32. + TYPES ty_extension TYPE zif_oassh_sftp_one_shot=>ty_extension. + TYPES ty_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. + TYPES ty_name TYPE zif_oassh_sftp_one_shot=>ty_name. + TYPES ty_names TYPE zif_oassh_sftp_one_shot=>ty_names. CONSTANTS c_max_packet_length TYPE i VALUE 262144. CONSTANTS: BEGIN OF c_state, diff --git a/src/zif_oassh_interactive_exec.intf.abap b/src/zif_oassh_interactive_exec.intf.abap new file mode 100644 index 0000000..e9a4567 --- /dev/null +++ b/src/zif_oassh_interactive_exec.intf.abap @@ -0,0 +1,46 @@ +INTERFACE zif_oassh_interactive_exec + PUBLIC. + +* Interactive command channel. Call exec_open( ) once, exchange binary data +* with exec_write( ) and exec_read( ), then finish with exec_close( ). close( ) +* closes the underlying SSH socket and remains the final cleanup operation. + METHODS exec_open + IMPORTING + iv_command TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING + zcx_oassh_error. + METHODS exec_write + IMPORTING + iv_data TYPE xstring + RAISING + zcx_oassh_error. + METHODS exec_read + IMPORTING + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_oassh_error. + METHODS exec_eof + RAISING + zcx_oassh_error. + METHODS exec_close + IMPORTING + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING + zcx_oassh_error. + METHODS exec_is_closed + RETURNING + VALUE(rv_closed) TYPE abap_bool. + METHODS get_stderr + RETURNING + VALUE(rv_output) TYPE string. + METHODS get_exit_status + RETURNING + VALUE(rv_status) TYPE i. + METHODS get_disconnect_reason + RETURNING + VALUE(rv_reason) TYPE i. + METHODS close. +ENDINTERFACE. diff --git a/src/zif_oassh_interactive_exec.intf.xml b/src/zif_oassh_interactive_exec.intf.xml new file mode 100644 index 0000000..f4e1346 --- /dev/null +++ b/src/zif_oassh_interactive_exec.intf.xml @@ -0,0 +1,15 @@ + + + + + + ZIF_OASSH_INTERACTIVE_EXEC + E + open-abap-ssh - Interactive exec + 2 + 1 + X + + + + diff --git a/src/zif_oassh_sftp_one_shot.intf.abap b/src/zif_oassh_sftp_one_shot.intf.abap new file mode 100644 index 0000000..8cad535 --- /dev/null +++ b/src/zif_oassh_sftp_one_shot.intf.abap @@ -0,0 +1,106 @@ +INTERFACE zif_oassh_sftp_one_shot + PUBLIC. + +* One SFTP operation per SSH connection. Each sftp_* method owns the SFTP +* channel lifecycle. Call close( ) afterwards to close the underlying socket. + TYPES ty_uint32 TYPE x LENGTH 4. + TYPES ty_uint64 TYPE x LENGTH 8. + TYPES: + BEGIN OF ty_extension, + extension_type TYPE xstring, + extension_data TYPE xstring, + END OF ty_extension. + TYPES ty_extensions TYPE STANDARD TABLE OF ty_extension WITH EMPTY KEY. + TYPES: + BEGIN OF ty_attrs, + flags TYPE ty_uint32, + has_size TYPE abap_bool, + size TYPE ty_uint64, + has_uid_gid TYPE abap_bool, + uid TYPE ty_uint32, + gid TYPE ty_uint32, + has_permissions TYPE abap_bool, + permissions TYPE ty_uint32, + has_acmodtime TYPE abap_bool, + atime TYPE ty_uint32, + mtime TYPE ty_uint32, + extensions TYPE ty_extensions, + END OF ty_attrs. + TYPES: + BEGIN OF ty_name, + filename TYPE xstring, + longname TYPE xstring, + attrs TYPE ty_attrs, + END OF ty_name. + TYPES ty_names TYPE STANDARD TABLE OF ty_name WITH EMPTY KEY. + METHODS sftp_download + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_oassh_error. + METHODS sftp_upload + IMPORTING + iv_path TYPE string + iv_data TYPE xstring + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING + zcx_oassh_error. + METHODS sftp_stat + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rs_attrs) TYPE ty_attrs + RAISING + zcx_oassh_error. + METHODS sftp_lstat + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rs_attrs) TYPE ty_attrs + RAISING + zcx_oassh_error. + METHODS sftp_list + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rt_names) TYPE ty_names + RAISING + zcx_oassh_error. + METHODS sftp_mkdir + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_rmdir + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_remove + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_rename + IMPORTING + iv_old_path TYPE string + iv_new_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_realpath + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING VALUE(rs_name) TYPE ty_name + RAISING zcx_oassh_error. + METHODS get_disconnect_reason + RETURNING + VALUE(rv_reason) TYPE i. + METHODS close. +ENDINTERFACE. diff --git a/src/zif_oassh_sftp_one_shot.intf.xml b/src/zif_oassh_sftp_one_shot.intf.xml new file mode 100644 index 0000000..d3c76a8 --- /dev/null +++ b/src/zif_oassh_sftp_one_shot.intf.xml @@ -0,0 +1,15 @@ + + + + + + ZIF_OASSH_SFTP_ONE_SHOT + E + open-abap-ssh - One-shot SFTP + 2 + 1 + X + + + + diff --git a/src/zif_oassh_sftp_session.intf.abap b/src/zif_oassh_sftp_session.intf.abap new file mode 100644 index 0000000..6ab4580 --- /dev/null +++ b/src/zif_oassh_sftp_session.intf.abap @@ -0,0 +1,89 @@ +INTERFACE zif_oassh_sftp_session + PUBLIC. + +* Reusable SFTP channel. Call sftp_open( ) once, run sequential sftp_* +* operations, then call sftp_close( ) and close( ). + TYPES ty_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. + TYPES ty_name TYPE zif_oassh_sftp_one_shot=>ty_name. + TYPES ty_names TYPE zif_oassh_sftp_one_shot=>ty_names. + METHODS sftp_open + IMPORTING + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING + zcx_oassh_error. + METHODS sftp_close + IMPORTING + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING + zcx_oassh_error. + METHODS sftp_download + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rv_data) TYPE xstring + RAISING + zcx_oassh_error. + METHODS sftp_upload + IMPORTING + iv_path TYPE string + iv_data TYPE xstring + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING + zcx_oassh_error. + METHODS sftp_stat + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rs_attrs) TYPE ty_attrs + RAISING + zcx_oassh_error. + METHODS sftp_lstat + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rs_attrs) TYPE ty_attrs + RAISING + zcx_oassh_error. + METHODS sftp_list + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING + VALUE(rt_names) TYPE ty_names + RAISING + zcx_oassh_error. + METHODS sftp_mkdir + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_rmdir + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_remove + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_rename + IMPORTING + iv_old_path TYPE string + iv_new_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RAISING zcx_oassh_error. + METHODS sftp_realpath + IMPORTING + iv_path TYPE string + iv_timeout_seconds TYPE i DEFAULT 300 + RETURNING VALUE(rs_name) TYPE ty_name + RAISING zcx_oassh_error. + METHODS get_disconnect_reason + RETURNING + VALUE(rv_reason) TYPE i. + METHODS close. +ENDINTERFACE. diff --git a/src/zif_oassh_sftp_session.intf.xml b/src/zif_oassh_sftp_session.intf.xml new file mode 100644 index 0000000..ddd0fbf --- /dev/null +++ b/src/zif_oassh_sftp_session.intf.xml @@ -0,0 +1,15 @@ + + + + + + ZIF_OASSH_SFTP_SESSION + E + open-abap-ssh - Reusable SFTP + 2 + 1 + X + + + + From 602258567d32dcf0c75df5035787e36d113b89c2 Mon Sep 17 00:00:00 2001 From: Lars Hvam Date: Wed, 15 Jul 2026 15:08:11 +0200 Subject: [PATCH 2/2] cleanup --- docs/sftp-sessions.md | 4 ++-- examples/zoassh_example_sftp.prog.abap | 2 +- src/zcl_oassh.clas.abap | 10 ++++----- src/zcl_oassh.clas.testclasses.abap | 8 +++---- src/zcl_oassh_sftp.clas.abap | 27 ++++++++++-------------- src/zcl_oassh_sftp.clas.testclasses.abap | 8 +++---- src/zif_oassh_sftp_session.intf.abap | 14 ++++++------ 7 files changed, 33 insertions(+), 40 deletions(-) diff --git a/docs/sftp-sessions.md b/docs/sftp-sessions.md index 21d23af..77c5a66 100644 --- a/docs/sftp-sessions.md +++ b/docs/sftp-sessions.md @@ -13,9 +13,9 @@ methods then run inside that single subsystem channel until `sftp_close`. ```abap DATA li_sftp TYPE REF TO zif_oassh_sftp_session. -DATA lt_names TYPE zif_oassh_sftp_session=>ty_names. +DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names. DATA lv_data TYPE xstring. -DATA ls_attrs TYPE zif_oassh_sftp_session=>ty_attrs. +DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. li_sftp = zcl_oassh=>connect( iv_host = 'ssh.example.com' diff --git a/examples/zoassh_example_sftp.prog.abap b/examples/zoassh_example_sftp.prog.abap index 1396a6c..202cdac 100644 --- a/examples/zoassh_example_sftp.prog.abap +++ b/examples/zoassh_example_sftp.prog.abap @@ -45,7 +45,7 @@ FORM run. DATA lo_host_verifier TYPE REF TO zif_oassh_host_verifier. DATA li_sftp TYPE REF TO zif_oassh_sftp_session. - DATA lt_names TYPE zif_oassh_sftp_session=>ty_names. + DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names. DATA lv_filename TYPE string. DATA lv_data TYPE xstring. DATA lv_preview TYPE string. diff --git a/src/zcl_oassh.clas.abap b/src/zcl_oassh.clas.abap index 8fe4cc4..390949c 100644 --- a/src/zcl_oassh.clas.abap +++ b/src/zcl_oassh.clas.abap @@ -172,21 +172,21 @@ CLASS zcl_oassh DEFINITION iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 RETURNING - VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs + VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs RAISING zcx_oassh_error. METHODS sftp_lstat IMPORTING iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 RETURNING - VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs + VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs RAISING zcx_oassh_error. METHODS sftp_list IMPORTING iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 RETURNING - VALUE(rt_names) TYPE zcl_oassh_sftp=>ty_names + VALUE(rt_names) TYPE zif_oassh_sftp_one_shot=>ty_names RAISING zcx_oassh_error. METHODS sftp_mkdir IMPORTING @@ -214,7 +214,7 @@ CLASS zcl_oassh DEFINITION iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 RETURNING - VALUE(rs_name) TYPE zcl_oassh_sftp=>ty_name + VALUE(rs_name) TYPE zif_oassh_sftp_one_shot=>ty_name RAISING zcx_oassh_error. METHODS handle_transport_message @@ -295,7 +295,7 @@ CLASS zcl_oassh DEFINITION iv_lstat TYPE abap_bool iv_timeout_seconds TYPE i RETURNING - VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs + VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs RAISING zcx_oassh_error. METHODS sftp_mutation diff --git a/src/zcl_oassh.clas.testclasses.abap b/src/zcl_oassh.clas.testclasses.abap index a6edc2f..5eb83df 100644 --- a/src/zcl_oassh.clas.testclasses.abap +++ b/src/zcl_oassh.clas.testclasses.abap @@ -930,7 +930,7 @@ CLASS ltcl_test IMPLEMENTATION. DATA lv_inbound_a TYPE xstring. DATA lv_inbound_b TYPE xstring. DATA lv_inbound TYPE xstring. - DATA lt_names TYPE zcl_oassh_sftp=>ty_names. + DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names. lo_mock = NEW #( ). li_socket = lo_mock. @@ -978,7 +978,7 @@ CLASS ltcl_test IMPLEMENTATION. DATA li_socket TYPE REF TO zif_oassh_socket. DATA li_random TYPE REF TO zif_oassh_random. DATA li_verifier TYPE REF TO zif_oassh_host_verifier. - DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs. + DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. lo_mock = NEW #( ). li_socket = lo_mock. @@ -2236,9 +2236,9 @@ CLASS ltcl_test IMPLEMENTATION. DATA li_socket TYPE REF TO zif_oassh_socket. DATA li_random TYPE REF TO zif_oassh_random. DATA li_verifier TYPE REF TO zif_oassh_host_verifier. - DATA lt_names TYPE zcl_oassh_sftp=>ty_names. + DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names. DATA lv_data TYPE xstring. - DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs. + DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. lo_mock = NEW #( ). li_socket = lo_mock. diff --git a/src/zcl_oassh_sftp.clas.abap b/src/zcl_oassh_sftp.clas.abap index 92fdae7..38fb26c 100644 --- a/src/zcl_oassh_sftp.clas.abap +++ b/src/zcl_oassh_sftp.clas.abap @@ -4,11 +4,6 @@ CLASS zcl_oassh_sftp DEFINITION CREATE PUBLIC. PUBLIC SECTION. - TYPES ty_uint32 TYPE zif_oassh_sftp_one_shot=>ty_uint32. - TYPES ty_extension TYPE zif_oassh_sftp_one_shot=>ty_extension. - TYPES ty_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. - TYPES ty_name TYPE zif_oassh_sftp_one_shot=>ty_name. - TYPES ty_names TYPE zif_oassh_sftp_one_shot=>ty_names. CONSTANTS c_max_packet_length TYPE i VALUE 262144. CONSTANTS: BEGIN OF c_state, @@ -109,12 +104,12 @@ CLASS zcl_oassh_sftp DEFINITION VALUE(rv_status) TYPE i. METHODS get_attrs RETURNING - VALUE(rs_attrs) TYPE ty_attrs. + VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs. METHODS get_names RETURNING - VALUE(rt_names) TYPE ty_names. + VALUE(rt_names) TYPE zif_oassh_sftp_one_shot=>ty_names. METHODS get_realpath - RETURNING VALUE(rs_name) TYPE ty_name. + RETURNING VALUE(rs_name) TYPE zif_oassh_sftp_one_shot=>ty_name. PRIVATE SECTION. TYPES ty_request_ids TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line. @@ -152,9 +147,9 @@ CLASS zcl_oassh_sftp DEFINITION DATA mv_upload_data TYPE xstring. DATA mv_upload_position TYPE i. DATA mv_write_length TYPE i. - DATA ms_attrs TYPE ty_attrs. - DATA mt_names TYPE ty_names. - DATA ms_realpath TYPE ty_name. + DATA ms_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. + DATA mt_names TYPE zif_oassh_sftp_one_shot=>ty_names. + DATA ms_realpath TYPE zif_oassh_sftp_one_shot=>ty_name. METHODS frame IMPORTING @@ -288,12 +283,12 @@ CLASS zcl_oassh_sftp DEFINITION io_packet TYPE REF TO zcl_oassh_stream iv_require_consumed TYPE abap_bool DEFAULT abap_true RETURNING - VALUE(rs_attrs) TYPE ty_attrs + VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs RAISING zcx_oassh_error. CLASS-METHODS flag_is_set IMPORTING - iv_flags TYPE ty_uint32 + iv_flags TYPE zif_oassh_sftp_one_shot=>ty_uint32 iv_bit TYPE i RETURNING VALUE(rv_set) TYPE abap_bool. @@ -996,7 +991,7 @@ CLASS zcl_oassh_sftp IMPLEMENTATION. DATA lv_status TYPE i. DATA lv_count TYPE i. DATA lv_total TYPE i. - DATA ls_name TYPE ty_name. + DATA ls_name TYPE zif_oassh_sftp_one_shot=>ty_name. CASE mv_state. WHEN c_state-opendir_pending. CASE iv_type. @@ -1090,11 +1085,11 @@ CLASS zcl_oassh_sftp IMPLEMENTATION. METHOD parse_attrs. * Section 5 fixes both field order and flag semantics. Unsupported v3 bits * are a protocol error; raw unsigned values remain byte-exact for portable ABAP. - DATA lv_flags TYPE ty_uint32. + DATA lv_flags TYPE zif_oassh_sftp_one_shot=>ty_uint32. DATA lv_bit_index TYPE i. DATA lv_bit TYPE c LENGTH 1. DATA lv_count TYPE i. - DATA ls_extension TYPE ty_extension. + DATA ls_extension TYPE zif_oassh_sftp_one_shot=>ty_extension. lv_flags = io_packet->take( 4 ). lv_bit_index = 2. WHILE lv_bit_index <= 28. diff --git a/src/zcl_oassh_sftp.clas.testclasses.abap b/src/zcl_oassh_sftp.clas.testclasses.abap index a11373d..0c2bd39 100644 --- a/src/zcl_oassh_sftp.clas.testclasses.abap +++ b/src/zcl_oassh_sftp.clas.testclasses.abap @@ -492,7 +492,7 @@ CLASS ltcl_test IMPLEMENTATION. METHOD stat_attrs. * Sections 5 and 6.8: flags determine the exact order of every ATTRS field. DATA lv_out TYPE xstring. - DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs. + DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. lv_out = mo_sftp->start_stat( 'a' ). lv_out = mo_sftp->receive( '000000050200000003' ). cl_abap_unit_assert=>assert_equals( @@ -548,7 +548,7 @@ CLASS ltcl_test IMPLEMENTATION. METHOD stat_extensions. * Unknown extension values are preserved as opaque byte strings. DATA lv_out TYPE xstring. - DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs. + DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. lv_out = mo_sftp->start_stat( 'a' ). lv_out = mo_sftp->receive( '000000050200000003' ). lv_out = mo_sftp->receive( '0000002169000000018000000000000002000000016100000000000000016200000002CCCC' ). @@ -612,7 +612,7 @@ CLASS ltcl_test IMPLEMENTATION. METHOD list_directory. * OPENDIR -> HANDLE -> repeated READDIR/NAME -> EOF -> CLOSE/OK. DATA lv_out TYPE xstring. - DATA lt_names TYPE zcl_oassh_sftp=>ty_names. + DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names. lv_out = mo_sftp->start_list( 'd' ). lv_out = mo_sftp->receive( '000000050200000003' ). cl_abap_unit_assert=>assert_equals( @@ -785,7 +785,7 @@ CLASS ltcl_test IMPLEMENTATION. METHOD realpath_name. DATA lv_out TYPE xstring. - DATA ls_name TYPE zcl_oassh_sftp=>ty_name. + DATA ls_name TYPE zif_oassh_sftp_one_shot=>ty_name. lv_out = mo_sftp->start_realpath( '.' ). lv_out = mo_sftp->receive( '000000050200000003' ). cl_abap_unit_assert=>assert_equals( diff --git a/src/zif_oassh_sftp_session.intf.abap b/src/zif_oassh_sftp_session.intf.abap index 6ab4580..65b93f7 100644 --- a/src/zif_oassh_sftp_session.intf.abap +++ b/src/zif_oassh_sftp_session.intf.abap @@ -2,10 +2,8 @@ INTERFACE zif_oassh_sftp_session PUBLIC. * Reusable SFTP channel. Call sftp_open( ) once, run sequential sftp_* -* operations, then call sftp_close( ) and close( ). - TYPES ty_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs. - TYPES ty_name TYPE zif_oassh_sftp_one_shot=>ty_name. - TYPES ty_names TYPE zif_oassh_sftp_one_shot=>ty_names. +* operations, then call sftp_close( ) and close( ). Result types are owned by +* zif_oassh_sftp_one_shot and referenced directly by both SFTP contracts. METHODS sftp_open IMPORTING iv_timeout_seconds TYPE i DEFAULT 300 @@ -36,7 +34,7 @@ INTERFACE zif_oassh_sftp_session iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 RETURNING - VALUE(rs_attrs) TYPE ty_attrs + VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs RAISING zcx_oassh_error. METHODS sftp_lstat @@ -44,7 +42,7 @@ INTERFACE zif_oassh_sftp_session iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 RETURNING - VALUE(rs_attrs) TYPE ty_attrs + VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs RAISING zcx_oassh_error. METHODS sftp_list @@ -52,7 +50,7 @@ INTERFACE zif_oassh_sftp_session iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 RETURNING - VALUE(rt_names) TYPE ty_names + VALUE(rt_names) TYPE zif_oassh_sftp_one_shot=>ty_names RAISING zcx_oassh_error. METHODS sftp_mkdir @@ -80,7 +78,7 @@ INTERFACE zif_oassh_sftp_session IMPORTING iv_path TYPE string iv_timeout_seconds TYPE i DEFAULT 300 - RETURNING VALUE(rs_name) TYPE ty_name + RETURNING VALUE(rs_name) TYPE zif_oassh_sftp_one_shot=>ty_name RAISING zcx_oassh_error. METHODS get_disconnect_reason RETURNING