免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7017 | 回复: 8
打印 上一主题 下一主题

[cgi脚本]CGIc输出图片问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-07-18 12:51 |只看该作者 |倒序浏览
问题 一:
  我下载编译了cgic205中的cgictest.c cgic.c cgic.h 文件,放在在我的Apche2.2的cgi-bin目录中。
我打开浏览器调用cgi-bin/cgitest.exe 显示正常上传文本文件回显正常。可是上传.gif图片回显是一堆乱码,难道cgitest.c文件显示不了图片吗?要怎么改才能回显图片呢?
我搜过一篇显示图片的文章是用setmode(fileno(stdout),O_BINARY)函数原文如下:

  “如果你的脚本发送图形数据,使用面向字符的流则意味着立即失败。解决方法是将流切换到二进制模式。在C语言中,可以使用setmode函数:setmode(fileno(stdout),O_BINARY)。通过setmode(fi1eno(stdout),O_TEXT)在流当中进行切换。一个典型的图形脚本以字符模式输出头部,而后切换到二进制模式用于图形数据。”

但是我不会用
问题二:
  还有一个问题就是我看到cgic.c文件中为什么把setmode(fileno(stdout),O_BINARY)函数写成这样:
#ifdef WIN32
        /* 1.07: Must set stdin and stdout to binary mode */
        /* 2.0: this is particularly crucial now and must not be removed */
        _setmode( _fileno( stdin ), _O_BINARY );
        _setmode( _fileno( stdout ), _O_BINARY );
#endif /* WIN32 */
  难道写windows 平台程序要#define WIN32 吗?
  我没#define WIN32  我的cgitest.exe为什么也能照样运行呢?
问题一代码:
  请老大们帮忙改一下附上cgitest.c原码:(可能只改 file()函数就行)
* Change this if the SERVER_NAME environment variable does not report
        the true name of your web server. */
#if 1
#define SERVER_NAME cgiServerName
#endif
#if 0
#define SERVER_NAME "www.boutell.com"
#endif

/* You may need to change this, particularly under Windows;
        it is a reasonable guess as to an acceptable place to
        store a saved environment in order to test that feature.
        If that feature is not important to you, you needn't
        concern yourself with this. */

#ifdef WIN32
#define SAVED_ENVIRONMENT "c:\\cgicsave.env"
#else
#define SAVED_ENVIRONMENT "/tmp/cgicsave.env"
#endif /* WIN32 */

#include <stdio.h>
#include "cgic.h"
#include <string.h>
#include <stdlib.h>

void HandleSubmit();
void ShowForm();
void CookieSet();
void Name();
void Address();
void Hungry();
void Temperature();
void Frogs();
void Color();
void Flavors();
void NonExButtons();
void RadioButtons();
void File();
void Entries();
void Cookies();
void LoadEnvironment();
void SaveEnvironment();

int cgiMain() {
#ifdef DEBUG
        LoadEnvironment();
#endif /* DEBUG */
        /* Load a previously saved CGI scenario if that button
                has been pressed. */
        if (cgiFormSubmitClicked("loadenvironment") == cgiFormSuccess) {
                LoadEnvironment();
        }
        /* Set any new cookie requested. Must be done *before*
                outputting the content type. */
        CookieSet();
        /* Send the content type, letting the browser know this is HTML */
        cgiHeaderContentType("text/html");
        /* Top of the page */
        fprintf(cgiOut, "<HTML><HEAD>\n");
        fprintf(cgiOut, "<TITLE>cgic test</TITLE></HEAD>\n");
        fprintf(cgiOut, "<BODY><H1>cgic test</H1>\n");
        /* If a submit button has already been clicked, act on the
                submission of the form. */
        if ((cgiFormSubmitClicked("testcgic") == cgiFormSuccess) ||
                cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess)
        {
                HandleSubmit();
                fprintf(cgiOut, "<hr>\n");
        }
        /* Now show the form */
        ShowForm();
        /* Finish up the page */
        fprintf(cgiOut, "</BODY></HTML>\n");
        return 0;
}

void HandleSubmit()
{
        Name();
        Address();
        Hungry();
        Temperature();
        Frogs();
        Color();
        Flavors();
        NonExButtons();
        RadioButtons();
        File();
        Entries();
        Cookies();
        /* The saveenvironment button, in addition to submitting the form,
                also saves the resulting CGI scenario to disk for later
                replay with the 'load saved environment' button. */
        if (cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess) {
                SaveEnvironment();
        }
}

void Name() {
        char name[81];
        cgiFormStringNoNewlines("name", name, 81);
        fprintf(cgiOut, "Name: ");
        cgiHtmlEscape(name);
        fprintf(cgiOut, "<BR>\n");
}
       
void Address() {
        char address[241];
        cgiFormString("address", address, 241);
        fprintf(cgiOut, "Address: <PRE>\n");
        cgiHtmlEscape(address);
        fprintf(cgiOut, "</PRE>\n");
}

void Hungry() {
        if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) {
                fprintf(cgiOut, "I'm Hungry!<BR>\n");
        } else {
                fprintf(cgiOut, "I'm Not Hungry!<BR>\n");
        }
}
       
void Temperature() {
        double temperature;
        cgiFormDoubleBounded("temperature", &temperature, 80.0, 120.0, 98.6);
        fprintf(cgiOut, "My temperature is %f.<BR>\n", temperature);
}
       
void Frogs() {
        int frogsEaten;
        cgiFormInteger("frogs", &frogsEaten, 0);
        fprintf(cgiOut, "I have eaten %d frogs.<BR>\n", frogsEaten);
}

char *colors[] = {
        "Red",
        "Green",
        "Blue"
};

void Color() {
        int colorChoice;
        cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0);
        fprintf(cgiOut, "I am: %s<BR>\n", colors[colorChoice]);
}         

char *flavors[] = {
        "pistachio",
        "walnut",
        "creme"
};

void Flavors() {
        int flavorChoices[3];
        int i;
        int result;       
        int invalid;
        result = cgiFormSelectMultiple("flavors", flavors, 3,
                flavorChoices, &invalid);
        if (result == cgiFormNotFound) {
                fprintf(cgiOut, "I hate ice cream.<p>\n");
        } else {       
                fprintf(cgiOut, "My favorite ice cream flavors are:\n");
                fprintf(cgiOut, "<ul>\n");
                for (i=0; (i < 3); i++) {
                        if (flavorChoices) {
                                fprintf(cgiOut, "<li>%s\n", flavors);
                        }
                }
                fprintf(cgiOut, "</ul>\n");
        }
}

char *ages[] = {
        "1",
        "2",
        "3",
        "4"
};

void RadioButtons() {
        int ageChoice;
        char ageText[10];
        /* Approach #1: check for one of several valid responses.
                Good if there are a short list of possible button values and
                you wish to enumerate them. */
        cgiFormRadio("age", ages, 4, &ageChoice, 0);

        fprintf(cgiOut, "Age of Truck: %s (method #1)<BR>\n",
                ages[ageChoice]);

        /* Approach #2: just get the string. Good
                if the information is not critical or if you wish
                to verify it in some other way. Note that if
                the information is numeric, cgiFormInteger,
                cgiFormDouble, and related functions may be
                used instead of cgiFormString. */       
        cgiFormString("age", ageText, 10);

        fprintf(cgiOut, "Age of Truck: %s (method #2)<BR>\n", ageText);
}

char *votes[] = {
        "A",
        "B",
        "C",
        "D"
};

void NonExButtons() {
        int voteChoices[4];
        int i;
        int result;       
        int invalid;

        char **responses;

        /* Method #1: check for valid votes. This is a good idea,
                since votes for nonexistent candidates should probably
                be discounted... */
        fprintf(cgiOut, "Votes (method 1):<BR>\n");
        result = cgiFormCheckboxMultiple("vote", votes, 4,
                voteChoices, &invalid);
        if (result == cgiFormNotFound) {
                fprintf(cgiOut, "I hate them all!<p>\n");
        } else {       
                fprintf(cgiOut, "My preferred candidates are:\n");
                fprintf(cgiOut, "<ul>\n");
                for (i=0; (i < 4); i++) {
                        if (voteChoices) {
                                fprintf(cgiOut, "<li>%s\n", votes);
                        }
                }
                fprintf(cgiOut, "</ul>\n");
        }

        /* Method #2: get all the names voted for and trust them.
                This is good if the form will change more often
                than the code and invented responses are not a danger
                or can be checked in some other way. */
        fprintf(cgiOut, "Votes (method 2):<BR>\n");
        result = cgiFormStringMultiple("vote", &responses);
        if (result == cgiFormNotFound) {       
                fprintf(cgiOut, "I hate them all!<p>\n");
        } else {
                int i = 0;
                fprintf(cgiOut, "My preferred candidates are:\n");
                fprintf(cgiOut, "<ul>\n");
                while (responses) {
                        fprintf(cgiOut, "<li>%s\n", responses);
                        i++;
                }
                fprintf(cgiOut, "</ul>\n");
        }
        /* We must be sure to free the string array or a memory
                leak will occur. Simply calling free() would free
                the array but not the individual strings. The
                function cgiStringArrayFree() does the job completely. */       
        cgiStringArrayFree(responses);
}

void Entries()
{
        char **array, **arrayStep;
        fprintf(cgiOut, "List of All Submitted Form Field Names:<p>\n");
        if (cgiFormEntries(&array) != cgiFormSuccess) {
                return;
        }
        arrayStep = array;
        fprintf(cgiOut, "<ul>\n");
        while (*arrayStep) {
                fprintf(cgiOut, "<li>");
                cgiHtmlEscape(*arrayStep);
                fprintf(cgiOut, "\n");
                arrayStep++;
        }
        fprintf(cgiOut, "</ul>\n");
        cgiStringArrayFree(array);
}

void Cookies()
{
        char **array, **arrayStep;
        char cname[1024], cvalue[1024];
        fprintf(cgiOut, "Cookies Submitted On This Call, With Values (Many Browsers NEVER Submit Cookies):<p>\n");
        if (cgiCookies(&array) != cgiFormSuccess) {
                return;
        }
        arrayStep = array;
        fprintf(cgiOut, "<table border=1>\n");
        fprintf(cgiOut, "<tr><th>Cookie<th>Value</tr>\n");
        while (*arrayStep) {
                char value[1024];
                fprintf(cgiOut, "<tr>");
                fprintf(cgiOut, "<td>");
                cgiHtmlEscape(*arrayStep);
                fprintf(cgiOut, "<td>");
                cgiCookieString(*arrayStep, value, sizeof(value));
                cgiHtmlEscape(value);
                fprintf(cgiOut, "\n");
                arrayStep++;
        }
        fprintf(cgiOut, "</table>\n");
        cgiFormString("cname", cname, sizeof(cname));       
        cgiFormString("cvalue", cvalue, sizeof(cvalue));       
        if (strlen(cname)) {
                fprintf(cgiOut, "New Cookie Set On This Call:<p>\n");
                fprintf(cgiOut, "Name: ");       
                cgiHtmlEscape(cname);
                fprintf(cgiOut, "Value: ");       
                cgiHtmlEscape(cvalue);
                fprintf(cgiOut, "<p>\n");
                fprintf(cgiOut, "If your browser accepts cookies (many do not), this new cookie should appear in the above list the next time the form is submitted.<p>\n");
        }
        cgiStringArrayFree(array);
}
       
void File()
{
        cgiFilePtr file;
        char name[1024];
        char contentType[1024];
        char buffer[1024];
        int size;
        int got;
        if (cgiFormFileName("file", name, sizeof(name)) != cgiFormSuccess) {
                printf("<p>No file was uploaded.<p>\n");
                return;
        }
        fprintf(cgiOut, "The filename submitted was: ");
        cgiHtmlEscape(name);
        fprintf(cgiOut, "<p>\n");
        cgiFormFileSize("file", &size);
        fprintf(cgiOut, "The file size was: %d bytes<p>\n", size);
        cgiFormFileContentType("file", contentType, sizeof(contentType));
        fprintf(cgiOut, "The alleged content type of the file was: ");
        cgiHtmlEscape(contentType);
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "Of course, this is only the claim the browser made when uploading the file. Much like the filename, it cannot be trusted.<p>\n");
        fprintf(cgiOut, "The file's contents are shown here:<p>\n");
        if (cgiFormFileOpen("file", &file) != cgiFormSuccess) {
                fprintf(cgiOut, "Could not open the file.<p>\n");
                return;
        }
        fprintf(cgiOut, "<pre>\n");
        while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) ==
                cgiFormSuccess)
        {
                cgiHtmlEscapeData(buffer, got);
        }
        fprintf(cgiOut, "</pre>\n");
        cgiFormFileClose(file);
}

void ShowForm()
{
        fprintf(cgiOut, "<!-- 2.0: multipart/form-data is required for file uploads. -->");
        fprintf(cgiOut, "<form method=\"POST\" enctype=\"multipart/form-data\" ");
        fprintf(cgiOut, "        action=\"");
        cgiValueEscape(cgiScriptName);
        fprintf(cgiOut, "\">\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "Text Field containing Plaintext\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "<input type=\"text\" name=\"name\">Your Name\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "Multiple-Line Text Field\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "<textarea NAME=\"address\" ROWS=4 COLS=40>\n");
        fprintf(cgiOut, "Default contents go here. \n");
        fprintf(cgiOut, "</textarea>\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "Checkbox\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "<input type=\"checkbox\" name=\"hungry\" checked>Hungry\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "Text Field containing a Numeric Value\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "<input type=\"text\" name=\"temperature\" value=\"98.6\">\n");
        fprintf(cgiOut, "Blood Temperature (80.0-120.0)\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "Text Field containing an Integer Value\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "<input type=\"text\" name=\"frogs\" value=\"1\">\n");
        fprintf(cgiOut, "Frogs Eaten\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "Single-SELECT\n");
        fprintf(cgiOut, "<br>\n");
        fprintf(cgiOut, "<select name=\"colors\">\n");
        fprintf(cgiOut, "<option value=\"Red\">Red\n");
        fprintf(cgiOut, "<option value=\"Green\">Green\n");
        fprintf(cgiOut, "<option value=\"Blue\">Blue\n");
        fprintf(cgiOut, "</select>\n");
        fprintf(cgiOut, "<br>\n");
        fprintf(cgiOut, "Multiple-SELECT\n");
        fprintf(cgiOut, "<br>\n");
        fprintf(cgiOut, "<select name=\"flavors\" multiple>\n");
        fprintf(cgiOut, "<option value=\"pistachio\">Pistachio\n");
        fprintf(cgiOut, "<option value=\"walnut\">Walnut\n");
        fprintf(cgiOut, "<option value=\"creme\">Creme\n");
        fprintf(cgiOut, "</select>\n");
        fprintf(cgiOut, "<p>Exclusive Radio Button Group: Age of Truck in Years\n");
        fprintf(cgiOut, "<input type=\"radio\" name=\"age\" value=\"1\">1\n");
        fprintf(cgiOut, "<input type=\"radio\" name=\"age\" value=\"2\">2\n");
        fprintf(cgiOut, "<input type=\"radio\" name=\"age\" value=\"3\" checked>3\n");
        fprintf(cgiOut, "<input type=\"radio\" name=\"age\" value=\"4\">4\n");
        fprintf(cgiOut, "<p>Nonexclusive Checkbox Group: Voting for Zero through Four Candidates\n");
        fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" value=\"A\">A\n");
        fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" value=\"B\">B\n");
        fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" value=\"C\">C\n");
        fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" value=\"D\">D\n");
        fprintf(cgiOut, "<p>File Upload:\n");
        fprintf(cgiOut, "<input type=\"file\" name=\"file\" value=\"\"> (Select A Local File)\n");
        fprintf(cgiOut, "<p>\n");
        fprintf(cgiOut, "<p>Set a Cookie<p>\n");
        fprintf(cgiOut, "<input name=\"cname\" value=\"\"> Cookie Name\n");
        fprintf(cgiOut, "<input name=\"cvalue\" value=\"\"> Cookie Value<p>\n");
        fprintf(cgiOut, "<input type=\"submit\" name=\"testcgic\" value=\"Submit Request\">\n");
        fprintf(cgiOut, "<input type=\"reset\" value=\"Reset Request\">\n");
        fprintf(cgiOut, "<p>Save the CGI Environment<p>\n");
        fprintf(cgiOut, "Pressing this button will submit the form, then save the CGI environment so that it can be replayed later by calling cgiReadEnvironment (in a debugger, for instance).<p>\n");
        fprintf(cgiOut, "<input type=\"submit\" name=\"saveenvironment\" value=\"Save Environment\">\n");
        fprintf(cgiOut, "</form>\n");
}

void CookieSet()
{
        char cname[1024];
        char cvalue[1024];
        /* Must set cookies BEFORE calling cgiHeaderContentType */
        cgiFormString("cname", cname, sizeof(cname));       
        cgiFormString("cvalue", cvalue, sizeof(cvalue));       
        if (strlen(cname)) {
                /* Cookie lives for one day (or until browser chooses
                        to get rid of it, which may be immediately),
                        and applies only to this script on this site. */       
                cgiHeaderCookieSetString(cname, cvalue,
                        86400, cgiScriptName, SERVER_NAME);
        }
}

void LoadEnvironment()
{
        if (cgiReadEnvironment(SAVED_ENVIRONMENT) !=
                cgiEnvironmentSuccess)
        {
                cgiHeaderContentType("text/html");
                fprintf(cgiOut, "<head>Error</head>\n");
                fprintf(cgiOut, "<body><h1>Error</h1>\n");
                fprintf(cgiOut, "cgiReadEnvironment failed. Most "
                        "likely you have not saved an environment "
                        "yet.\n");
                exit(0);
        }
        /* OK, return now and show the results of the saved environment */
}

void SaveEnvironment()
{
        if (cgiWriteEnvironment(SAVED_ENVIRONMENT) !=
                cgiEnvironmentSuccess)
        {
                fprintf(cgiOut, "<p>cgiWriteEnvironment failed. Most "
                        "likely %s is not a valid path or is not "
                        "writable by the user that the CGI program "
                        "is running as.<p>\n", SAVED_ENVIRONMENT);
        } else {
                fprintf(cgiOut, "<p>Environment saved. Click this button "
                        "to restore it, playing back exactly the same "
                        "scenario: "
                        "<form method=POST action=\"");
                cgiValueEscape(cgiScriptName);
                fprintf(cgiOut, "\">"
                        "<input type=\"submit\" "
                        "value=\"Load Environment\" "
                        "name=\"loadenvironment\"></form><p>\n");
        }
}

[ 本帖最后由 fuer 于 2006-7-22 13:02 编辑 ]

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
2 [报告]
发表于 2006-07-18 13:10 |只看该作者
1. setmode不是可以切换么

2. #define WIN32
这个是为了代码的通用把,在*nix下面也可以通用。

论坛徽章:
0
3 [报告]
发表于 2006-07-18 13:38 |只看该作者
上面的viod file() 函数在给它上船文本文件是回显正常,可是在给它上传.gif图片时回显乱码,我知道要用到这个setmode()函数但是我不知道在viod file()函数里用在哪里才能让上传的.gif图片回显正常。
  请指教

论坛徽章:
0
4 [报告]
发表于 2006-07-19 14:55 |只看该作者
size=1]没人会吗?难道这问题很难?那位老大发发慈悲帮帮我啊!

论坛徽章:
0
5 [报告]
发表于 2006-07-20 18:00 |只看该作者
1. setmode 是 windows 平台上设置控制台(console)程序输入输出模式的函数,
    windows 默认的是字符模块, 而非二进制模式. 在传送图片等, 二进制文件必须进行模式转换.

>> 我没#define WIN32  我的cgitest.exe为什么也能照样运行呢?
2. WIN32 是 VC++ 等 windows 编译器默认已经设置了的一个宏, 即命令行 cl.exe /DWIN32

>> 我知道要用到这个setmode()函数但是我不知道在viod file()函数里用在哪里才能让上传的.gif图片回显正常。
3.  仔细看下 file() 这个函数就会知道, 这个程序仅意在演示上传文本文件, 未对二进制文件进行处理.  
     二进制文件要自已写程序存取.


文件上传, 可以参考下:
http://www.eybuild.com/develop/demoshow.htm
http://bbs.chinaunix.net/viewthr ... &extra=page%3D2



另外, 直接用 cgic, clib 等编写CGI 具有很多局限性.

论坛徽章:
0
6 [报告]
发表于 2006-07-20 18:11 |只看该作者
原帖由 newzy 于 2006-7-20 18:00 发表
1. setmode 是 windows 平台上设置控制台(console)程序输入输出模式的函数,
    windows 默认的是字符模块, 而非二进制模式. 在传送图片等, 二进制文件必须进行模式转换.

谢谢newzy的回复。
  还得麻烦你
  能告诉我怎样用setmode在cgi程序中输出图片文件吗?

论坛徽章:
0
7 [报告]
发表于 2006-07-20 19:33 |只看该作者

回复 6楼 fuer 的帖子

那位老大能告诉我怎么在c写的cgi程序中输出图片呀?

论坛徽章:
0
8 [报告]
发表于 2006-07-21 08:49 |只看该作者
参照下这个帖子:
http://bbs.chinaunix.net/viewthread.php?tid=773572

首先根据输出文件的类型确定 mime 头信息,
如果是一般文件mime头请用 text/plain 类型, jpg 图image/jpeg, gif 图片 image/gif, ...
其次确定输出文件的文件名, 和要输入的内容,
如果是图片, 可以边从文件读出, 读边 fwrite(buff, len, 1, stdout).

如,

  1. main()
  2. {
  3. #ifdef WIN32
  4.         _setmode( _fileno( stdout ), _O_BINARY );
  5. #endif /* WIN32 */

  6. printf("Content-Type: text/plain\n");
  7. printf("Content-Disposition: attachment; filename=test.txt\n\n");
  8. printf("Hello world, this is a test file, name: test.txt");

  9. }
复制代码


建议:
C 写 CGI 不妨试试专业 开发CGI 的C 工具 CSP/eybuild
http://www.eybuild.com

祝你好运
wojiukao 该用户已被删除
9 [报告]
发表于 2006-12-14 11:10 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP