笔者之前的文章,曾经介绍过 ABAP 和 C 语言的关系:
笔者的 SAP 技术交流群里,近期有朋友提问:
下面这句 ABAP 语句是什么意思 , 是获取文件名和文件夹吗?具体是从哪里获取?
call 'ALERTS' id 'ADMODE' field ad_rzl
id 'OPCODE' field rzl_op_rd_dir
id 'FILE_NAME' field full_name
id 'DIR_TBL' field line_tbl-*sys*.
在 ABAP 帮助文档里,将这种通过 CALL 关键字进行的函数调用,标记为 System Function Call - 系统函数调用,只能由 SAP 内部使用,不建议用于应用开发。
CALL 后跟的系统函数名称,需要在 SAP Kernel 源文件 sapctab.h 里声明,并且修改此类系统函数,需要重新编译和链接 ABAP Kernel.
SAP 社区上有一篇文章,作者为 ABAP Product Owner 团队成员之一,给大家介绍了此类 System Function Call 的更多细节:
https://community.sap.com/t5/application-development-blog-posts/a-word-about-call-system/ba-p/12987614
文章提到了不建议在应用程序里使用 CALL 来调用系统函数的一些理由。
1. 安全隐患
CALL 关键字不应该在应用开发程序里使用,首先是因为其容易受到系统命令注入攻击(System Command Injection)。
所谓系统命令,即操作系统提供的指令,用于执行特定任务,比如文件操作、网络通讯、进程管理等。
在 Unix/Linux 系统中,常用的系统命令有 ls, cat, grep 等,在 Windows 系统中,有 dir, type, netstat 这些命令。
系统命令注入攻击,发生在程序将用户输入作为系统命令的一部分,而没有适当的校验和过滤。攻击者通过构造特定的输入,可以让程序执行非预期的系统命令,从而达到执行恶意操作的目的。
在没有适当的安全检查和过滤时,攻击者可以通过巧妙构造的输入来插入和执行任意命令。
以笔者这篇文章提到的代码为例,仅仅简单数行 ABAP 代码,就能直接在 ABAP 程序里,通过 CALL 'SYSTEM' ID 'COMMAND', 调用 ABAP 应用服务器所运行的 Linux 操作系统里的任意系统命令。
使用 ABAP 在 SAPGUI 里直接执行 Linux 操作系统的命令
因此如果我们的应用程序里,使用到了这些被 SAP 帮助文档明确标注为禁用的 CALL 语句,无疑是给程序开了一个大大的安全漏洞。
更安全的做法是使用 SXPG_CALL_SYSTEM 或SXPG_COMMAND_EXECUTE 这些 Function Module.
2. 朝不保夕
RZ11 事务码里,有一个配置参数 rdisp/call_system,可以直接将这种 CALL 调用关闭。
假设一个包含了 CALL 语句的 ABAP 应用程序已经编写好,运行没有问题。如果管理员在 RZ11 事务码里将这个参数设置为 0 即 Deactivated,那么之前工作正常的应用程序,执行时就会遇到 ABAP Runtime Errors.
3. 没有文档
因为这些系统调用仅供内部使用,所以函数名称和每个参数的作用,不可能在 help.sap.com 上找到说明。
因此要了解这些系统调用的使用方法,除了根据源代码 Google,以及阅读源代码本身的注释外,也没有其他好办法了。
比如本文开头有朋友在笔者技术交流群里问到的那个例子。
使用 Google 把源代码粘贴进去然后搜索,发现搜索结果几乎全部指向一个 Function Module:RZL_READ_DIR_LOCAL
这个函数的作用是读取当前应用服务器所在操作系统上指定路径下的文件和目录名称。
比如笔者使用的 ABAP 服务器,根目录 / 下有 42 个文件夹和文件目录。这些内容和登录到操作系统 Shell 之后,执行 ls / 命令看到的内容是一致的。
下图的 RZL_OP_RD_DIR,其实是硬编码的变量,其含义可以通过源代码里的注释获得,代表目录的读取操作。
而 LINE_TBL-*SYS* 算是古董级的内表语法了,等价于 LINE_TBL[].
关于这种古怪的内表写法的更多细节,请参阅笔者的文章: