⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file.c

📁 基于minigui的浏览器. 这是最新版本.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * File: file.c :) * * Copyright (C) 2000 - 2004 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. *//* * Directory scanning is no longer streamed, but it gets sorted instead! * Directory entries on top, files next. * With new HTML layout. */#include <pthread.h>#include <ctype.h>           /* for tolower */#include <errno.h>           /* for errno */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <sys/un.h>#include <dirent.h>#include <fcntl.h>#include <time.h>#include <signal.h>#include <glib.h>#include "../dpip/dpip.h"#include "dpiutil.h"#define MAXNAMESIZE 30#define HIDE_DOTFILES TRUE#define _MSG(fmt...)#define MSG(fmt...)  g_print("[file dpi]: " fmt)enum {   FILE_OK,   FILE_NOT_FOUND,   FILE_NO_ACCESS};typedef struct {   char *full_path;   const char *filename;   off_t size;   mode_t mode;   time_t mtime;} FileInfo;typedef struct {   char *dirname;   GList *flist;       /* List of files and subdirectories (for sorting) */} DilloDir;typedef struct {   SockHandler *sh;   gint status;   gint old_style;   pthread_t thrID;   gint done;} ClientInfo;/* * Forward references */static const char *File_content_type(const char *filename);static gint File_get_file(ClientInfo *Client,                          const gchar *filename,                          struct stat *sb,                          const char *orig_url);static gint File_get_dir(ClientInfo *Client,                         const gchar *DirName,                         const char *orig_url);/* * Global variables */static volatile gint DPIBYE = 0;static volatile gint ThreadRunning = 0;static gint OLD_STYLE = 0;/* A list for the clients we are serving */static GList *Clients = NULL;/* a mutex for operations on clients */static pthread_mutex_t ClMut;/* * Close a file descriptor, but handling EINTR */static void File_close(int fd){   while (close(fd) < 0 && errno == EINTR)      ;}/* * Detects 'Content-Type' when the server does not supply one. * It uses the magic(5) logic from file(1). Currently, it * only checks the few mime types that Dillo supports. * * 'Data' is a pointer to the first bytes of the raw data. * (this is based on a_Misc_get_content_type_from_data()) */static const gchar *File_get_content_type_from_data(void *Data, size_t Size){   static const gchar *Types[] = {      "application/octet-stream",      "text/html", "text/plain",      "image/gif", "image/png", "image/jpeg",   };   gint Type = 0;   gchar *p = Data;   size_t i, non_ascci;   _MSG("File_get_content_type_from_data:: Size = %d\n", Size);   /* HTML try */   for (i = 0; i < Size && isspace(p[i]); ++i);   if ((Size - i >= 5  && !g_strncasecmp(p+i, "<html", 5)) ||       (Size - i >= 5  && !g_strncasecmp(p+i, "<head", 5)) ||       (Size - i >= 6  && !g_strncasecmp(p+i, "<title", 6)) ||       (Size - i >= 14 && !g_strncasecmp(p+i, "<!doctype html", 14)) ||       /* this line is workaround for FTP through the Squid proxy */       (Size - i >= 17 && !g_strncasecmp(p+i, "<!-- HTML listing", 17))) {      Type = 1;   /* Images */   } else if (Size >= 4 && !g_strncasecmp(p, "GIF8", 4)) {      Type = 3;   } else if (Size >= 4 && !g_strncasecmp(p, "\x89PNG", 4)) {      Type = 4;   } else if (Size >= 2 && !g_strncasecmp(p, "\xff\xd8", 2)) {      /* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking       * at the character representation should be machine independent. */      Type = 5;   /* Text */   } else {      /* We'll assume "text/plain" if the set of chars above 127 is <= 10       * in a 256-bytes sample.  Better heuristics are welcomed! :-) */      non_ascci = 0;      Size = MIN (Size, 256);          for (i = 0; i < Size; i++)          if ((unsigned char) p[i] > 127)            ++non_ascci;      if (Size == 256) {         Type = (non_ascci > 10) ? 0 : 2;      } else {         Type = (non_ascci > 0) ? 0 : 2;      }   }   return (Types[Type]);}/* * Compare two FileInfo pointers * This function is used for sorting directories */static gint File_comp(gconstpointer a, gconstpointer b){   FileInfo *f1 = (FileInfo *) a;   FileInfo *f2 = (FileInfo *) b;   if (S_ISDIR(f1->mode)) {      if (S_ISDIR(f2->mode)) {         return strcmp(f1->filename, f2->filename);      } else {         return -1;      }   } else {      if (S_ISDIR(f2->mode)) {         return 1;      } else {         return strcmp(f1->filename, f2->filename);      }   }}/* * Allocate a DilloDir structure, set safe values in it and sort the entries. */static DilloDir *File_dillodir_new(char *dirname){   struct stat sb;   struct dirent *de;   DIR *dir;   DilloDir *Ddir;   FileInfo *finfo;   char *fname;   int dirname_len;   if ( !(dir = opendir(dirname)))      return NULL;   Ddir = g_new(DilloDir, 1);   Ddir->dirname = g_strdup(dirname);   Ddir->flist = NULL;   dirname_len = strlen(Ddir->dirname);   /* Scan every name and sort them */   while ((de = readdir(dir)) != 0) {      if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))         continue;              /* skip "." and ".." */      if (HIDE_DOTFILES) {         /* Don't add hidden files or backup files to the list */         if (de->d_name[0] == '.' ||             de->d_name[0] == '#' ||             (de->d_name[0] != '\0' &&              de->d_name[strlen(de->d_name) - 1] == '~'))            continue;      }      fname = g_strdup_printf("%s/%s", Ddir->dirname, de->d_name);      if (stat(fname, &sb) == -1) {         g_free(fname);         continue;              /* ignore files we can't stat */      }      finfo = g_new(FileInfo, 1);      finfo->full_path = fname;      finfo->filename = fname + dirname_len + 1;      finfo->size = sb.st_size;      finfo->mode = sb.st_mode;      finfo->mtime = sb.st_mtime;      Ddir->flist = g_list_prepend(Ddir->flist, finfo);   }   closedir(dir);   /* sort the entries */   Ddir->flist = g_list_sort(Ddir->flist, File_comp);   return Ddir;}/* * Deallocate a DilloDir structure. */static void File_dillodir_free(DilloDir *Ddir){   GList *list;   for (list = Ddir->flist; list; list = g_list_next(list)) {      FileInfo *finfo = list->data;      g_free(finfo->full_path);      g_free(finfo);   }   g_list_free(Ddir->flist);   g_free(Ddir->dirname);   g_free(Ddir);}/* * Output the string for parent directory */static void File_print_parent_dir(ClientInfo *Client, const char *dirname){   if (strcmp(dirname, "/") != 0) {        /* Not the root dir */      char *p, *parent, *HUparent, *Uparent;      parent = g_strdup(dirname);      /* cut trailing slash */      parent[strlen(parent) - 1] = '\0';      /* make 'parent' have the parent dir path */      if ( (p = strrchr(parent, '/')) )         *(p + 1) = '\0';      Uparent = Escape_uri_str(parent, NULL);      HUparent = Escape_html_str(Uparent);      sock_handler_printf(Client->sh, 0,         "<a href='file:%s'>Parent directory</a>", HUparent);      g_free(HUparent);      g_free(Uparent);      g_free(parent);   }}/* * Given a timestamp, output an HTML-formatted date string. */static void File_print_mtime(ClientInfo *Client, time_t mtime){   char *ds = ctime(&mtime);   /* Month, day and {hour or year} */   if (Client->old_style) {      sock_handler_printf(Client->sh, 0, " %.3s %.2s", ds + 4, ds + 8);      if (time(NULL) - mtime > 15811200) {         sock_handler_printf(Client->sh, 0, "  %.4s", ds + 20);      } else {         sock_handler_printf(Client->sh, 0, " %.5s", ds + 11);      }   } else {      sock_handler_printf(Client->sh, 0,         "<td>%.3s&nbsp;%.2s&nbsp;%.5s", ds + 4, ds + 8,         /* (more than 6 months old) ? year : hour; */         (time(NULL) - mtime > 15811200) ? ds + 20 : ds + 11);   }}/* * Return a HTML-line from file info. */static void File_info2html(ClientInfo *Client,                           FileInfo *finfo, const char *dirname, gint n){   gint size;   char *sizeunits;   char namebuf[MAXNAMESIZE + 1];   char *Uref, *HUref, *Hname;   const char *ref, *filecont, *name = finfo->filename;   if (finfo->size <= 9999) {      size = finfo->size;      sizeunits = "bytes";   } else if (finfo->size / 1024 <= 9999) {      size = finfo->size / 1024 + (finfo->size % 1024 >= 1024 / 2);      sizeunits = "Kb";   } else {      size = finfo->size / 1048576 + (finfo->size % 1048576 >= 1048576 / 2);      sizeunits = "Mb";   }   /* we could note if it's a symlink... */   if S_ISDIR (finfo->mode) {      filecont = "Directory";   } else if (finfo->mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {      filecont = "Executable";   } else {      filecont = File_content_type(finfo->full_path);      if (!filecont || !strcmp(filecont, "application/octet-stream"))         filecont = "unknown";   }   ref = name;   if (strlen(name) > MAXNAMESIZE) {      memcpy(namebuf, name, MAXNAMESIZE - 3);      strcpy(namebuf + (MAXNAMESIZE - 3), "...");      name = namebuf;   }   /* escape problematic filenames */   Uref = Escape_uri_str(ref, NULL);   HUref = Escape_html_str(Uref);   Hname = Escape_html_str(name);   if (Client->old_style) {      char *dots = ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..";      gint ndots = MAXNAMESIZE - strlen(name);      sock_handler_printf(Client->sh, 0,         "%s<a href='%s'>%s</a>"         " %s"         " %-11s%4d %-5s",         S_ISDIR (finfo->mode) ? ">" : " ", HUref, Hname,         dots + 50 - (ndots > 0 ? ndots : 0),         filecont, size, sizeunits);   } else {      sock_handler_printf(Client->sh, 0,         "<tr align=center %s><td>%s<td align=left><a href='%s'>%s</a>"         "<td>%s<td>%d&nbsp;%s",         (n & 1) ? "bgcolor=#dcdcdc" : "",         S_ISDIR (finfo->mode) ? ">" : " ", HUref, Hname,         filecont, size, sizeunits);   }   File_print_mtime(Client, finfo->mtime);   sock_handler_printf(Client->sh, 0, "\n");   g_free(Hname);   g_free(HUref);   g_free(Uref);}/* * Read a local directory and translate it to html. */static void File_transfer_dir(ClientInfo *Client,                              DilloDir *Ddir, const char *orig_url){   gint n;   GList *list;   char *d_cmd, *Hdirname, *Udirname, *HUdirname;   /* Send DPI header */   d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", orig_url);   sock_handler_write_str(Client->sh, d_cmd, 1);   g_free(d_cmd);   /* Send page title */   Udirname = Escape_uri_str(Ddir->dirname, NULL);   HUdirname = Escape_html_str(Udirname);   Hdirname = Escape_html_str(Ddir->dirname);   sock_handler_printf(Client->sh, 0,      "Content-Type: text/html\n\n"      "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n"      "<HTML>\n<HEAD>\n <BASE href='file:%s'>\n"      " <TITLE>file:%s</TITLE>\n</HEAD>\n"      "<BODY><H1>Directory listing of %s</H1>\n",      HUdirname, Hdirname, Hdirname);   g_free(Hdirname);   g_free(HUdirname);   g_free(Udirname);   if (Client->old_style) {      sock_handler_printf(Client->sh, 0, "<pre>\n");   }   /* Output the parent directory */   File_print_parent_dir(Client, Ddir->dirname);   /* HTML style toggle */   sock_handler_printf(Client->sh, 0,      "&nbsp;&nbsp;<a href='dpi:/file/toggle'>%%</a>\n");   if (Ddir->flist) {      if (Client->old_style) {         sock_handler_printf(Client->sh, 0, "\n\n");      } else {         sock_handler_printf(Client->sh, 0,            "<br><br>\n"            "<table border=0 cellpadding=1 cellspacing=0"            " bgcolor=#E0E0E0 width=100%%>\n"            "<tr align=center>\n"            "<td>\n"            "<td width=60%%><b>Filename</b>"            "<td><b>Type</b>"            "<td><b>Size</b>"            "<td><b>Modified&nbsp;at</b>\n");      }   } else {      sock_handler_printf(Client->sh, 0, "<br><br>Directory is empty...");   }   /* Output entries */   for (n = 0, list = Ddir->flist; list; list = g_list_next(list)) {      File_info2html(Client, list->data, Ddir->dirname, ++n);   }   if (Ddir->flist) {      if (Client->old_style) {         sock_handler_printf(Client->sh, 0, "</pre>\n");      } else {         sock_handler_printf(Client->sh, 0, "</table>\n");      }   }   sock_handler_printf(Client->sh, 0, "</BODY></HTML>\n");}/* * Return a content type based on the extension of the filename. */static const char *File_ext(const char *filename){   char *e;   if ( !(e = strrchr(filename, '.')) )      return NULL;   e++;   if (!strcasecmp(e, "gif")) {      return "image/gif";   } else if (!strcasecmp(e, "jpg") ||              !strcasecmp(e, "jpeg")) {      return "image/jpeg";   } else if (!strcasecmp(e, "png")) {      return "image/png";   } else if (!strcasecmp(e, "html") ||              !strcasecmp(e, "htm") ||              !strcasecmp(e, "shtml")) {      return "text/html";   } else {      return NULL;   }}/* * Based on the extension, return the content_type for the file. * (if there's no extension, analyze the data and try to figure it out) */static const char *File_content_type(const char *filename){   gint fd;   struct stat sb;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -