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 <webview/file_reply.h>
24 
25 #include <core/exceptions/system.h>
26 #include <utils/system/filetype.h>
27 
28 #include <cerrno>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 
32 namespace fawkes {
33 #if 0 /* just to make Emacs auto-indent happy */
34 }
35 #endif
36 
37 /** @class DynamicFileWebReply <webview/file_reply.h>
38  * Dynamic raw file transfer reply.
39  * This dynamic file transfer reply transmits the given file with a mime type
40  * determined with libmagic.
41  * @author Tim Niemueller
42  */
43 
44 /** Constructor.
45  * @param filename path and name of the file to transmit
46  */
48  : DynamicWebReply(WebReply::HTTP_OK), __close_when_done(true)
49 {
50  if (access(filename, R_OK) != 0 || ((__file = fopen(filename, "r")) == NULL)) {
51  throw fawkes::CouldNotOpenFileException(filename, errno);
52  }
53 
54  determine_file_size();
55 
56  add_header("Content-type", fawkes::mimetype_file(filename));
57 }
58 
59 /** Constructor.
60  * @param file file handle of file to transmit
61  * @param close_when_done true to close file after transmission is completed
62  */
63 DynamicFileWebReply::DynamicFileWebReply(FILE *file, bool close_when_done)
65  __file(file), __close_when_done(close_when_done)
66 {
67  fseek(__file, 0, SEEK_SET);
68  determine_file_size();
69  try {
70  add_header("Content-type", fawkes::mimetype_file(dup(fileno(__file))));
71  } catch (Exception &e) {} // ignored
72  fseek(__file, 0, SEEK_SET);
73 }
74 
75 /** Destructor. */
77 {
78  if (__close_when_done) fclose(__file);
79  __file = NULL;
80 }
81 
82 
83 void
84 DynamicFileWebReply::determine_file_size()
85 {
86  struct stat sbuf;
87  fstat(fileno(__file), &sbuf);
88 
89  if ( S_ISDIR(sbuf.st_mode) ) {
90  throw fawkes::Exception("Cannot send directory\n");
91  }
92  __size = sbuf.st_size;
93 }
94 
95 size_t
97 {
98  return __size;
99 }
100 
101 size_t
102 DynamicFileWebReply::next_chunk(size_t pos, char *buffer, size_t buf_max_size)
103 {
104  if ( (fseek(__file, pos, SEEK_SET) == -1) || feof(__file) ) {
105  return (size_t)-1;
106  }
107  return fread(buffer, 1, buf_max_size, __file);
108 }
109 
110 } // end namespace fawkes
DynamicFileWebReply(const char *filename)
Constructor.
Definition: file_reply.cpp:47
File could not be opened.
Definition: system.h:53
virtual size_t size()
Total size of the web reply.
Definition: file_reply.cpp:96
Fawkes library namespace.
void add_header(std::string header, std::string content)
Add a HTTP header.
Definition: reply.cpp:97
virtual ~DynamicFileWebReply()
Destructor.
Definition: file_reply.cpp:76
std::string mimetype_file(const char *filename)
Get mime-type of file.
Definition: filetype.cpp:112
Dynamic web reply.
Definition: reply.h:123
Base class for exceptions in Fawkes.
Definition: exception.h:36
Basic web reply.
Definition: reply.h:36
virtual size_t next_chunk(size_t pos, char *buffer, size_t buf_max_size)
Get data of next chunk.
Definition: file_reply.cpp:102