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

📄 file.c

📁 基于minigui的浏览器. 这是最新版本.
💻 C
📖 第 1 页 / 共 2 页
字号:
   const gchar *ct;   gchar buf[256];   ssize_t buf_size;   if (!(ct = File_ext(filename))) {      /* everything failed, let's analyze the data... */      if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) != -1) {         if ((buf_size = read(fd, buf, 256)) == 256 ) {            ct = File_get_content_type_from_data(buf, (size_t)buf_size);         } else if (stat(filename, &sb) != -1 &&                    buf_size > 0 && buf_size == sb.st_size) {            ct = File_get_content_type_from_data(buf, (size_t)buf_size);         }         File_close(fd);      }   }   return ct;}/* * Try to stat the file and determine if it's readable. */static void File_get(ClientInfo *Client, const char *filename,                     const char *orig_url){   int res;   struct stat sb;   char *msg = NULL, *d_cmd;   if (stat(filename, &sb) != 0) {      /* stat failed, prepare a file-not-found error. */      res = FILE_NOT_FOUND;   } else if (S_ISDIR(sb.st_mode)) {      /* set up for reading directory */      res = File_get_dir(Client, filename, orig_url);   } else {      /* set up for reading a file */      res = File_get_file(Client, filename, &sb, orig_url);   }   if (res == FILE_NOT_FOUND) {      msg = g_strdup_printf("%s Not Found: %s",               S_ISDIR(sb.st_mode) ? "Directory" : "File", filename);   } else if (res == FILE_NO_ACCESS) {      msg = g_strdup_printf("Access denied to %s: %s",               S_ISDIR(sb.st_mode) ? "Directory" : "File", filename);   }   if (msg) {      d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "send_status_message", msg);      sock_handler_write_str(Client->sh, d_cmd, 1);      g_free(d_cmd);      g_free(msg);   }}/* * */static gint File_get_dir(ClientInfo *Client,                         const gchar *DirName, const char *orig_url){   GString *g_dirname;   DilloDir *Ddir;   /* Let's make sure this directory url has a trailing slash */   g_dirname = g_string_new(DirName);   if ( g_dirname->str[g_dirname->len - 1] != '/' )      g_string_append(g_dirname, "/");   /* Let's get a structure ready for transfer */   Ddir = File_dillodir_new(g_dirname->str);   g_string_free(g_dirname, TRUE);   if ( Ddir ) {      File_transfer_dir(Client, Ddir, orig_url);      File_dillodir_free(Ddir);      return FILE_OK;   } else      return FILE_NO_ACCESS;}/* * Send the MIME content/type and then send the file itself. */static gint File_get_file(ClientInfo *Client,                          const gchar *filename,                          struct stat *sb,                          const char *orig_url){#define LBUF 16*1024   const gchar *ct;   char buf[LBUF], *d_cmd;   gint fd, st;   if ( (fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0)      return FILE_NO_ACCESS;   /* Content-Type info is based on filename extension. If there's no    * known extension, then we do data sniffing. If this doesn't lead    * to a conclusion, "application/octet-stream" is sent.    */   if (!(ct = File_content_type(filename)))      ct = "application/octet-stream";   /* Send DPI command */   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 HTTP stream */   sock_handler_printf(Client->sh, 0,      "Content-Type: %s\n"      "Content-length: %ld\n\n",      ct, sb->st_size);   /* Send raw file contents */   do {      if ((st = read(fd, buf, LBUF)) > 0) {         if (sock_handler_write(Client->sh, buf, (size_t)st, 0) != 0)            break;      } else if (st < 0) {         perror("[read]");         if (errno == EINTR || errno == EAGAIN)            continue;      }   } while (st > 0);   /* todo: It may be better to send an error report to dillo instead of    * calling abort from g_error() */   if (st == -1)      g_error("ERROR while reading from file \"%s\", error was \"%s\"\n",              filename, strerror(errno));   File_close(fd);   return FILE_OK;}/* * Given an hex octet (e3, 2F, 20), return the corresponding * character if the octet is valid, and -1 otherwise */static int File_parse_hex_octet(const gchar *s){   gint hex_value;   gchar *tail, hex[3];   if ( (hex[0] = s[0]) && (hex[1] = s[1]) ) {      hex[2] = 0;      hex_value = strtol(hex, &tail, 16);      if (tail - hex == 2)        return hex_value;   }   return -1;}static void File_parse_hex_octets(char **str){   gchar *dest, *tmp, *orig = *str;   int i, val;   if (strchr(orig, '%')) {      dest = tmp = g_new(gchar, strlen(orig) + 1);      for (i = 0; orig[i]; i++) {         if (orig[i] == '%' &&             (val = File_parse_hex_octet(orig + i + 1)) >= 0) {            *dest++ = val;            i += 2;         } else {            *dest++ = orig[i];         }      }      *dest = '\0';      g_free(orig);      *str = tmp;   }}/* * Make a file URL into a human (and machine) readable path. * The idea is to always have a path that starts with only one slash. * Embedded slashes are ignored. */static char *File_normalize_path(const char *orig){   char *str = (char *) orig, *basename = NULL, *ret, *p;   /* Make sure the string starts with file: (it should, but...) */   if (strncmp(str, "file:", 5) != 0)      return NULL;   str += 5;   /* Skip slashes */   while (str[0] == '/' && str[1] != '\0' && str[1] == '/')      str++;   if (*str == '\0') {      /* Give CWD if the string is only "file:" */      basename = g_get_current_dir();   } else if (*str == '~') {      if (str[1] == '\0' || str[1] == '/') {         /* Expand 'tilde' to user's home */         basename = g_strdup(g_get_home_dir());         str++;      }   } else if (*str == '.') {      if (str[1] == '\0' || str[1] == '/') {         /* User wants the CWD */         basename = g_get_current_dir();         str++;      } else if (str[1] == '.') {         /* One level down from the CWD */         char *tmp1 = g_get_current_dir();         char *tmp2 = strrchr(tmp1, '/');         if (tmp2) {            basename = g_strndup(tmp1, (guint)(tmp2 - tmp1));         }         str += 2;         g_free(tmp1);      }   } else if (*str != '/') {      return NULL;   }   ret = g_strdup_printf("%s%s%s",                         basename ? basename : "",                         basename ? "/" : "",                         str);   g_free(basename);   /* remove the fragment if present */   if ((p = strrchr(ret, '#')) != NULL)      *p = 0;   /* Parse possible hexadecimal octets in the URI path */   File_parse_hex_octets(&ret);   return ret;}/* * Set the style flag and ask for a reload, so it shows inmediatly. */static void File_toggle_html_style(ClientInfo *Client){   char *d_cmd;   OLD_STYLE = !OLD_STYLE;   d_cmd = a_Dpip_build_cmd("cmd=%s", "reload_request");   sock_handler_write_str(Client->sh, d_cmd, 1);   g_free(d_cmd);}/* * Perform any necessary cleanups upon abnormal termination */static void termination_handler(int signum){  exit(signum);}/* Client handling ----------------------------------------------------------*//* * Add a new client to the list. */static ClientInfo *File_add_client(gint sock_fd){   ClientInfo *NewClient;   NewClient = g_new(ClientInfo, 1);   NewClient->sh = sock_handler_new(sock_fd, sock_fd, 8*1024);   NewClient->status = 0;   NewClient->done = 0;   NewClient->old_style = OLD_STYLE;  pthread_mutex_lock(&ClMut);   Clients = g_list_append(Clients, NewClient);  pthread_mutex_unlock(&ClMut);   return NewClient;}/* * Get client record by number */static void *File_get_client_n(guint n){   void *client;  pthread_mutex_lock(&ClMut);   client = g_list_nth_data(Clients, n);  pthread_mutex_unlock(&ClMut);   return client;}/* * Remove a client from the list. */static void File_remove_client_n(guint n){   ClientInfo *Client;  pthread_mutex_lock(&ClMut);   Client = g_list_nth_data(Clients, n);   Clients = g_list_remove(Clients, (void *)Client);  pthread_mutex_unlock(&ClMut);   _MSG("Closing Socket Handler\n");   sock_handler_close(Client->sh);   sock_handler_free(Client->sh);   g_free(Client);}/* * Return the number of clients. */static gint File_num_clients(void){   guint n;  pthread_mutex_lock(&ClMut);   n = g_list_length(Clients);  pthread_mutex_unlock(&ClMut);   return n;}/* * Serve this client. * (this function runs on its own thread) */static void *File_serve_client(void *data){   char *dpip_tag, *cmd = NULL, *url = NULL, *path;   ClientInfo *Client = data;   /* Read the dpi command */   dpip_tag = sock_handler_read(Client->sh);   MSG("dpip_tag={%s}\n", dpip_tag);   if (dpip_tag) {      cmd = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "cmd");      if (cmd) {         if (strcmp(cmd, "DpiBye") == 0) {            DPIBYE = 1;         } else {            url = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "url");            if (!url)               MSG("file.dpi:: Failed to parse 'url'\n");         }      }   }   g_free(cmd);   g_free(dpip_tag);   if (!DPIBYE && url) {      _MSG("url = '%s'\n", url);      path = File_normalize_path(url);      if (path) {         _MSG("path = '%s'\n", path);         File_get(Client, path, url);      } else if (strcmp(url, "dpi:/file/toggle") == 0) {         File_toggle_html_style(Client);      } else {         MSG("ERROR: URL path was %s\n", url);      }      g_free(path);   }   g_free(url);   /* flag the the transfer finished */   Client->done = 1;   return NULL;}/* * Serve the client queue. * (this function runs on its own thread) */static void *File_serve_clients(void *client){   /* switch to detached state */   pthread_detach(pthread_self());   while (File_num_clients()) {      client = File_get_client_n((guint)0);      File_serve_client(client);      File_remove_client_n((guint)0);   }   ThreadRunning = 0;   return NULL;}/* --------------------------------------------------------------------------*//* * Check a fd for activity, with a max timeout. * return value: 0 if timeout, 1 if input available, -1 if error. */int File_check_fd(int filedes, unsigned int seconds){  int st;  fd_set set;  struct timeval timeout;  /* Initialize the file descriptor set. */  FD_ZERO (&set);  FD_SET (filedes, &set);  /* Initialize the timeout data structure. */  timeout.tv_sec = seconds;  timeout.tv_usec = 0;  do {     st = select(FD_SETSIZE, &set, NULL, NULL, &timeout);  } while (st == -1 && errno == EINTR);  return st;}int main(void){   ClientInfo *NewClient;   struct sockaddr_un spun;   gint temp_sock_descriptor;   gint address_size, c_st, st = 1;   guint i;   /* Arrange the cleanup function for abnormal terminations */   if (signal (SIGINT, termination_handler) == SIG_IGN)     signal (SIGINT, SIG_IGN);   if (signal (SIGHUP, termination_handler) == SIG_IGN)     signal (SIGHUP, SIG_IGN);   if (signal (SIGTERM, termination_handler) == SIG_IGN)     signal (SIGTERM, SIG_IGN);   MSG("(v.1) accepting connections...\n");   /* initialize mutex */   pthread_mutex_init(&ClMut, NULL);   /* some OSes may need this... */   address_size = sizeof(struct sockaddr_un);   /* start the service loop */   while (!DPIBYE) {      /* wait for a connection */      do {         c_st = File_check_fd(STDIN_FILENO, 1);      } while (c_st == 0 && !DPIBYE);      if (c_st < 0) {         perror("[select]");         break;      }      if (DPIBYE)         break;      temp_sock_descriptor =         accept(STDIN_FILENO, (struct sockaddr *)&spun, &address_size);      if (temp_sock_descriptor == -1) {         perror("[accept]");         break;      }      /* Create and initialize a new client */      NewClient = File_add_client(temp_sock_descriptor);      if (!ThreadRunning) {         ThreadRunning = 1;         /* Serve the client from a thread (avoids deadlocks) */         if (pthread_create(&NewClient->thrID, NULL,                            File_serve_clients, NewClient) != 0) {            perror("[pthread_create]");            ThreadRunning = 0;            break;         }      }   }   /* todo: handle a running thread better. */   for (i = 0; i < 5 && ThreadRunning; ++i) {      MSG("sleep i=%u", i);      sleep(i);   }   if (DPIBYE)      st = 0;   return st;}

⌨️ 快捷键说明

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