Fawkes API  Fawkes Development Version
file_reply.cpp
1 
2 /***************************************************************************
3  * file_reply.cpp - Web request file reply
4  *
5  * Created: Thu Oct 23 14:00:17 2008
6  * Copyright 2006-2009 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include <core/exceptions/system.h>
24 #include <sys/stat.h>
25 #include <utils/system/filetype.h>
26 #include <webview/file_reply.h>
27 
28 #include <cerrno>
29 #include <unistd.h>
30 
31 namespace fawkes {
32 
33 /** @class DynamicFileWebReply <webview/file_reply.h>
34  * Dynamic raw file transfer reply.
35  * This dynamic file transfer reply transmits the given file with a mime type
36  * determined with libmagic.
37  * @author Tim Niemueller
38  */
39 
40 /** Constructor.
41  * @param filename path and name of the file to transmit
42  * @param content_type content type of file, will try to guess by
43  * magic if not given
44  */
45 DynamicFileWebReply::DynamicFileWebReply(const std::string &filename,
46  const std::string &content_type)
47 : DynamicWebReply(WebReply::HTTP_OK), close_when_done_(true)
48 {
49  if (access(filename.c_str(), R_OK) != 0 || ((file_ = fopen(filename.c_str(), "r")) == NULL)) {
50  throw fawkes::CouldNotOpenFileException(filename.c_str(), errno);
51  }
52 
53  determine_file_size();
54 
55  if (content_type.empty()) {
56  add_header("Content-type", fawkes::mimetype_file(filename.c_str()));
57  } else {
58  add_header("Content-type", content_type);
59  }
60 }
61 
62 /** Constructor.
63  * @param filename path and name of the file to transmit
64  */
66 : DynamicWebReply(WebReply::HTTP_OK), close_when_done_(true)
67 {
68  if (access(filename, R_OK) != 0 || ((file_ = fopen(filename, "r")) == NULL)) {
69  throw fawkes::CouldNotOpenFileException(filename, errno);
70  }
71 
72  determine_file_size();
73 
74  add_header("Content-type", fawkes::mimetype_file(filename));
75 }
76 
77 /** Constructor.
78  * @param file file handle of file to transmit
79  * @param close_when_done true to close file after transmission is completed
80  */
81 DynamicFileWebReply::DynamicFileWebReply(FILE *file, bool close_when_done)
82 : DynamicWebReply(WebReply::HTTP_OK), file_(file), close_when_done_(close_when_done)
83 {
84  fseek(file_, 0, SEEK_SET);
85  determine_file_size();
86  try {
87  add_header("Content-type", fawkes::mimetype_file(dup(fileno(file_))));
88  } catch (Exception &e) {
89  } // ignored
90  fseek(file_, 0, SEEK_SET);
91 }
92 
93 /** Destructor. */
95 {
96  if (close_when_done_)
97  fclose(file_);
98  file_ = NULL;
99 }
100 
101 void
102 DynamicFileWebReply::determine_file_size()
103 {
104  struct stat sbuf;
105  fstat(fileno(file_), &sbuf);
106 
107  if (S_ISDIR(sbuf.st_mode)) {
108  throw fawkes::Exception("Cannot send directory\n");
109  }
110  size_ = sbuf.st_size;
111 }
112 
113 size_t
115 {
116  return size_;
117 }
118 
119 size_t
120 DynamicFileWebReply::next_chunk(size_t pos, char *buffer, size_t buf_max_size)
121 {
122  if ((fseek(file_, pos, SEEK_SET) == -1) || feof(file_)) {
123  return (size_t)-1;
124  }
125  return fread(buffer, 1, buf_max_size, file_);
126 }
127 
128 } // end namespace fawkes
File could not be opened.
Definition: system.h:52
virtual size_t size()
Total size of the web reply.
Definition: file_reply.cpp:114
DynamicFileWebReply(const std::string &filename, const std::string &content_type="")
Constructor.
Definition: file_reply.cpp:45
Fawkes library namespace.
virtual ~DynamicFileWebReply()
Destructor.
Definition: file_reply.cpp:94
std::string mimetype_file(const char *filename)
Get mime-type of file.
Definition: filetype.cpp:111
Dynamic web reply.
Definition: reply.h:125
Base class for exceptions in Fawkes.
Definition: exception.h:35
Basic web reply.
Definition: reply.h:33
virtual size_t next_chunk(size_t pos, char *buffer, size_t buf_max_size)
Get data of next chunk.
Definition: file_reply.cpp:120
void add_header(const std::string &header, const std::string &content)
Add a HTTP header.
Definition: reply.cpp:123