在 Informix 4GL 程序中验证 URL

Posted

技术标签:

【中文标题】在 Informix 4GL 程序中验证 URL【英文标题】:Validate URL in Informix 4GL program 【发布时间】:2015-05-15 21:59:56 【问题描述】:

在我的 Informix 4GL 程序中,我有一个输入字段,用户可以在其中插入一个 URL,然后提要通过脚本发送到 Web。 如何在输入时验证 URL,以确保它是实时链接?我可以打个电话看看我是否收到任何错误信息吗?

【问题讨论】:

【参考方案1】:

I4GL 检查 URL

没有内置函数可以做到这一点(在 I4GL 被发明时,URL 并不存在)。

如果您可以设计一个 C 方法来执行此操作,您可以安排通过 C 接口调用该方法。您将在本机 C 中编写该方法,然后使用常规规则编写一个 I4GL 可调用的 C 接口函数。当您使用 I4GL c 代码构建程序时,您还将链接额外的 C 函数。如果您使用 I4GL-RDS(p 代码)构建程序,则需要构建一个自定义运行程序,并暴露额外的功能。所有这些都是 I4GL 的标准技术。

一般来说,您需要的 C 接口代码大致如下所示:

#include <fglsys.h>

// Standard interface for I4GL-callable C functions
extern int i4gl_validate_url(int nargs);

// Using obsolescent interface functions
int i4gl_validate_url(int nargs)

    if (nargs != 1)
        fgl_fatal(__FILE__, __LINE__, -1318);
    char url[4096];
    popstring(url, sizeof(url));
    int r = validate_url(url);     // Your C function
    retint(r);
    return 1;

您可以并且应该检查manuals,但是使用“旧样式”函数名称的代码应该可以正确编译。代码在 I4GL 中可以这样调用:

DEFINE url CHAR(256)
DEFINE rc  INTEGER

LET url = "http://www.google.com/"
LET rc = i4gl_validate_url(url)

IF rc != 0 THEN
    ERROR "Invalid URL"
ELSE
    MESSAGE "URL is OK"
END IF

或者沿着这些一般路线。您返回的确切值取决于您对如何从validate_url() 返回状态的决定。如果需要,您可以从接口函数返回多个值(例如错误号和错误消息的文本)。等等。这是关于调用一些 C 代码以从 I4GL 程序中验证 URL 的最简单的设计。

现代 C 接口函数

接口库中的函数名称在00年代中期全部更改,但旧名称仍以宏的形式存在。旧名称是:

popstring(char *buffer, int buflen) retint(int retval) fgl_fatal(const char *file, int line, int errnum)

您可以在4GL Reference Manual 中的IBM Informix 4GL v7.50.xC3: Publication library in PDF 找到修订后的文档,并且您需要附录C“将C 与IBM Informix 4GL 一起使用”。

新名称以ibm_lib4gl_开头:

ibm_libi4gl_popMInt() ibm_libi4gl_popString()

至于错误报告功能,有一个——它存在——但我无法再访问它的文档了。它将在 fglsys.h 标头中。它将错误号作为一个参数;有文件名和行号作为其他参数。并且它可能是ibm_lib4gl_…,并且名称的其余部分可能是Fatalfatal(或Errerr)。

I4GL 运行一个检查 URL 的脚本

写一个shell脚本来获取状态码不是更容易吗?如果我可以将状态代码或任何现有结果返回到程序中,这可能会起作用吗?我可以这样做吗?

很有可能。但是,如果您希望将 URL 的内容作为字符串,您最终可能会想要调用 C。当然值得考虑从 I4GL 中调用 shell 脚本是否可行。如果是这样,它会简单得多(RUN "script",IIRC,其中文字字符串可能会被包含命令和 URL 的构建字符串替换)。我相信现在I4GL中也有文件I/O功能,所以如果你能得到脚本来写一个文件(琐碎),你可以从文件中读取数据而不需要自定义C。很长一段时间,你需要自定义 C 来做到这一点。

我只需要在将 URL 存储到数据库之前对其进行验证。我在想:

#!/bin/bash

read -p "URL to check: " url
if curl --output /dev/null --silent --head --fail "$url"; then
    printf '%s\n' "$url exist"
else
    printf '%s\n' "$url does not exist"
fi

但我只需要将输出而不是 /dev/null 放入变量中。我相信唯一的选择是将输出转储到临时文件中并从那里读取。

不是让 I4GL 运行代码来验证 URL,而是让 I4GL 运行脚本来验证 URL。使用脚本的退出状态并将curl 的输出转储到/dev/null

FUNCTION check_url(url)

    DEFINE url VARCHAR(255)
    DEFINE command_line VARCHAR(255)
    DEFINE exit_status  INTEGER

    LET command_line = "check_url ", url
    RUN command_line RETURNING exit_status

    RETURN exit_status

END FUNCTION check_url

您的调用代码可以分析exit_status 以查看它是否有效。值为 0 表示成功;非零表示某种问题,可以认为是“URL 不起作用”。

确保check_url 脚本 (a) 在成功时以状态 0 退出,在任何类型的失败时以非零状态退出,并且 (b) 默认情况下不向标准输出(或标准错误)写入任何内容。写入标准错误或输出会搞砸屏幕布局等,而您不希望这样。 (您显然可以为脚本提供启用标准输出的选项,或者您可以使用选项调用脚本以抑制标准输出和标准错误,或者将输出重定向到/dev/null;但是,当被 I4GL 程序使用时,它应该保持沉默。)

您的“脚本”(check_url) 可以很简单:

#!/bin/bash

exec curl --output /dev/null --silent --head --fail "$1:-http://www.example.com/"

这会将第一个参数传递给curl,如果没有给出参数,则传递不存在的example.com URL,并将其自身替换为curl,这会根据需要生成零/非零退出状态。您可以在命令行末尾添加2&gt;/dev/null 以确保看不到错误消息。 (请注意,如果出现任何问题,调试将非常麻烦;请确保您已准备好进行调试。)

exec 是一个小优化;你可以省略它,结果几乎没有区别。 (我可以设计一个可能会发现差异的方案;它涉及向curl 进程发出信号,不过——kill -9 9999 或类似的,其中9999curl 进程的PID——而不是实际意义。)

鉴于脚本只是调用另一个程序的一行代码,因此可以将所有代码嵌入到 I4GL 程序中。然而,拥有一个外部 shell 脚本(或 Perl 脚本,或……)具有灵活性的优点。例如,您可以编辑它以记录尝试,而根本不更改 I4GL 代码。再分发一个文件,但灵活性更好——保留一个单独的脚本,即使它都可以嵌入到 I4GL 中。

【讨论】:

感谢乔纳森花时间回答这个问题。很有帮助。 写个shell脚本来获取状态码不是更简单吗?如果我可以将状态代码或任何现有结果返回到程序中,这可能会起作用吗?我可以这样做吗? 很有可能。但是,如果您希望将 URL 的内容作为字符串,您最终可能会想要调用 C。当然值得考虑从 I4GL 中调用 shell 脚本是否可行。如果是这样,它会简单得多(RUN "script",IIRC,其中文字字符串可能会被包含命令和 URL 的构建字符串替换)。我相信现在I4GL中也有文件I/O功能,所以如果你能得到脚本来写一个文件(琐碎),你可以从文件中读取数据而不需要自定义C。很长一段时间,你需要自定义 C 来做到这一点。 我只需要在将 URL 存储到数据库之前对其进行验证。我在想:#!/bin/bash read -p "URL to check:" url if curl --output /dev/null --silent --head --fail "$url";然后 printf '%s\n' "$url exists" else printf '%s\n' "$url doesn't exist" fi - 但我只需要将输出而不是 dev/null 放入变量中。我相信唯一的选择是将输出转储到临时文件中并从那里读取。 使用脚本的退出状态并将curl的输出转储到/dev/nullDEFINE command_line VARCHAR(255) DEFINE exit_status INTEGER …assign to command_line… RUN command_line RETURNING exit_status 然后分析exit_status 看是否有效(0 表示成功,非零表示某种问题,可以认为是'URL 不起作用')。【参考方案2】:

正如 Jonathan 所说,“当 I4GL 被发明时,URL 并不存在”。您会发现,已经发展到取代 Informix-4gl 的产品(例如 FourJs Genero)将迎合 I4GL 之后发明的新技术和其他事物。

使用 FourJs Genero,下面的代码将完成你熟悉的 Informix 4gl 语法之后的工作

IMPORT com
MAIN

    -- Should succeed and display 1
    DISPLAY validate_url("http://www.google.com")
    DISPLAY validate_url("http://www.4js.com/online_documentation/fjs-fgl-manual-html/index.html#c_fgl_nf.html") -- link to some of the features added to I4GL by Genero

    -- Should fail and display 0
    DISPLAY validate_url("http://www.google.com/testing")
    DISPLAY validate_url("http://www.google2.com")
END MAIN

FUNCTION validate_url(url)
DEFINE url STRING
DEFINE req com.HttpRequest
DEFINE resp com.HttpResponse

    -- Returns TRUE if http request to a URL returns 200
    TRY
        LET req = com.HttpRequest.create(url)
        CALL req.doRequest()
        LET resp = req.getResponse()
        IF resp.getStatusCode() = 200 THEN
            RETURN TRUE
        END IF
        -- May want to handle other HTTP status codes
    CATCH
        -- May want to capture case if not connected to internet etc
    END TRY
    RETURN FALSE 
END FUNCTION

【讨论】:

以上是关于在 Informix 4GL 程序中验证 URL的主要内容,如果未能解决你的问题,请参考以下文章

下午在 Informix 4GL 中显示

无法运行 Informix 4GL 交互式调试器

如何在 Informix 4gl 中引用 TEXT 类型?

在 INFORMIX 4GL 的报告中对“ORDER BY”使用“IF 语句”

Informix 4GL 向屏幕报告 - 反向

在 4GL Informix 中关闭“Wy-60”?