在Informix 4GL程序中验证URL

时间:2015-05-15 21:59:56

标签: url informix 4gl

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

2 个答案:

答案 0 :(得分:2)

I4GL检查网址

没有内置功能(当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但该代码,使用旧样式&#39;函数名称,应该正确编译。代码可以在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)

您可以在IBM Informix 4GL v7.50.xC3: Publication library in PDF4GL Reference Manual找到修订后的文档,您需要附录C&#34;将C与IBM Informix 4GL一起使用&#34;。

新名称开始ibm_lib4gl_

  • ibm_libi4gl_popMInt()
  • ibm_libi4gl_popString()

关于错误报告功能,有一个 - 它存在 - 但我不能再访问文档了。它将位于fglsys.h标题中。它将错误号作为一个参数;这里有文件名和行号作为其他参数。它可能会ibm_lib4gl_…,并且可能会Fatal或者fatal(或者Errerr)其余的名字。

I4GL运行检查URL的脚本

  

编写shell脚本以获取状态代码会不会更容易?如果我可以将状态代码或任何现有结果返回给程序变量,那可能会有用吗?我能这样做吗?

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

  

我只需要在将URL存储到数据库之前验证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表示成功;非零表示某种类型的问题,可以认为该网址不起作用。

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

您的脚本&#39; (check_url)可以简单如下:

#!/bin/bash

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

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

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

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

答案 1 :(得分:0)

正如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