📄 ftp.c
字号:
/* * Dpi for FTP. * * This server checks the ftp-URL to be a directory (requires wget). * If true, it sends back an html representation of it, and if not * a dpip message (which is catched by dillo who redirects the ftp URL * to the downloads server). * * THIS IS A PROTOTYPE to illustrate how it is done. Feel free to polish! * * Copyright 2003 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * *//* * TODO: * - Check dpi command syntax * - Handle simultaneous connections. * (note that if it becomes resident there's less forking). * - Send feedback about the FTP login process from wget's stderr. * i.e. capture our child's stderr, process it, and report back. * - Add error handling * - etc * * If ftp.dpi is implemented with a low level ftp library, it becomes * possible to keep the connection alive, and thus make browsing of ftp * directories faster (this avoids one login per page, and forks). Perhaps * it's not worth, but can be done. * * Currently, anything the user clicks is sent back to Dillo. This * may be better handled by inserting file type detection here. If * we detect a binary, the connection is aborted and a download request * dpi tag is sent instead. * * This ftp plugin profits from the fact that given no MIME type in * the HTTP header, dillo tries to detect the filetype itself. */#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <sys/wait.h>#include <errno.h>#include <sys/time.h>#include <glib.h>#define BUFLEN 256#define TOUT 300/*---------------------------------------------------------------------------*//* * Task: given a tag and an attribute name, return its value. * (character stuffing is removed here) * Return value: the attribute value, or NULL if not present or malformed. * (copied from bookmarks.c) */char *Get_attr_value(char *tag, int tagsize, char *attrname){ char *p, *q, *ltag, quote, *start, *val = NULL; ltag = g_strndup(tag, tagsize); if ((p = strstr(ltag, attrname)) && (p = strchr(p, '=')) && (p = strpbrk(p, "'\"")) ) { quote = *p; start = ++p; while ((q = strchr(p, quote)) && q[1] == quote) p = q + 2; if (q) { val = g_strndup(start, q - start); for (p = q = val; (*q = *p); ++p, ++q) if ((*p == '"' || *p == '\'') && p[1] == p[0]) ++p; } } g_free(ltag); return val;}/*---------------------------------------------------------------------------*//* * Build a shell command using wget for this URL. */gchar *make_wget_cmd(gchar *url){ gchar *p, *wcmd = NULL; if ((p = strrchr(url, '/')) != NULL){ /* if it does not end with a slash, append one */ wcmd = // g_strdup_printf("wget -O - %s%s 2>/dev/null", url, p[1] ? "/" : ""); g_strdup_printf("wget -O - '%s' 2>/dev/null", url); } return wcmd;}/* * Send the stream char by char (useful for slow transfer test) * Return value: bytes written */gint send_stream_1(FILE *in_stream, gchar *url){ gint i, ch; for (i = 0; (ch = fgetc(in_stream)) != EOF; ++i) { if (i == 0) { printf("<dpi cmd='start_send_page' url='%s'>", url); fflush(stdout); printf("Content-type: text/html\n\n"); fflush(stdout); } printf("%c", ch); g_printerr("%c", ch); fflush(stdout); } return i;}/* * Send the stream with default buffering (somewhat faster) * Return value: bytes written */gint send_stream_2(FILE *in_stream, gchar *url){ gint i, ch; for (i = 0; (ch = fgetc(in_stream)) != EOF; ++i) { if (i == 0) { printf("<dpi cmd='start_send_page' url='%s'>", url); printf("Content-type: text/html\n\n"); } printf("%c", ch); g_printerr("%c", ch); } return i;}/* * Send the stream with coarse buffering (fastest) * Return value: 1: data sent, 0: nothing sent */gint send_stream_3(FILE *in_stream, gchar *url){ gint header = 0; gchar buf[4096]; size_t n; while ((n = fread (buf, 1, 4096, in_stream)) > 0) { //g_printerr("ftp.dpi::fread: read n = %d bytes\n", n); if (n > 0 && !header) { printf("<dpi cmd='start_send_page' url='%s'>", url); //printf("Content-type: text/html\n\n"); printf("\n\n"); header = 1; } fwrite(buf, 1, n, stdout); //fwrite(buf, 1, n, stderr); }// g_printerr("ftp.dpi::fread: read n = %d bytes\n", n); return header;}/* * Fork, exec command, get its output and redirect to stdout. * Return: Number of bytes transfered. */gint try_ftp_transfer(gchar *wget_cmd, gchar *url){ FILE *in_stream; gint nb, ret; if ((in_stream = popen(wget_cmd, "r")) == NULL) { perror("popen"); exit (EXIT_FAILURE); } /* Read/Write */ nb = send_stream_3(in_stream, url); if ((ret = pclose(in_stream)) != 0) g_printerr("ftp.dpi::pclose: [%d] %s\n", ret, g_strerror(errno)); return nb;}/* * */int main(void){ FILE *F_stdin; gchar *dpip_tag = NULL, *cmd = NULL, *url = NULL, *url2 = NULL, *wget_cmd = NULL, *wget_cmd2 = NULL; gint nb, rd_len; gchar buf[4096], *p; /* wget may need to write a temporary file... */ chdir("/tmp"); /* Read the dpi command from STDIN */ F_stdin = fdopen (STDIN_FILENO, "r"); rd_len = read(STDIN_FILENO, buf, 4096); dpip_tag = g_strndup(buf, rd_len); fclose(F_stdin);// close(STDIN_FILENO); /* Necessary? */// g_printerr("[%s]\n", dpip_tag); cmd = Get_attr_value(dpip_tag, strlen(dpip_tag), "cmd"); url = Get_attr_value(dpip_tag, strlen(dpip_tag), "url"); if (!cmd || !url) { g_printerr("ftp.dpi:: Error, cmd=%s, url=%s\n", cmd, url); exit (EXIT_FAILURE); } /* make command string */ wget_cmd = make_wget_cmd(url); g_printerr("ftp.dpi::[%s]\n", wget_cmd); if ((nb = try_ftp_transfer(wget_cmd, url)) == 0) { /* Transfer failed, the requested file may not exist or be a symlnk * to a directory. Try again... */ if ((p = strrchr(url, '/')) && p[1]) { url2 = g_strconcat(url, "/", NULL); wget_cmd2 = make_wget_cmd(url2); nb = try_ftp_transfer(wget_cmd2, url); } } if (nb == 0) { /* The transfer failed, let dillo know... */ printf("<dpi cmd='answer' to_cmd='open_url' msg='not a directory'>"); fflush(stdout); } g_free(cmd); g_free(url); g_free(url2); g_free(dpip_tag); g_free(wget_cmd); g_free(wget_cmd2); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -