]> git.llucax.com Git - z.facultad/75.42/plaqui.git/blob - Server/src/httprequest.cpp
El Transmitter ya anda bien (se puede escuchar con un nc -p [puerto] -l -u :).
[z.facultad/75.42/plaqui.git] / Server / src / httprequest.cpp
1 // vim: set noexpandtab tabstop=4 shiftwidth=4:
2 //----------------------------------------------------------------------------
3 //                                  PlaQui
4 //----------------------------------------------------------------------------
5 // This file is part of PlaQui.
6 //
7 // PlaQui is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the Free Software
9 // Foundation; either version 2 of the License, or (at your option) any later
10 // version.
11 //
12 // PlaQui is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 // details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with PlaQui; if not, write to the Free Software Foundation, Inc., 59 Temple
19 // Place, Suite 330, Boston, MA  02111-1307  USA
20 //----------------------------------------------------------------------------
21 // Creado:  dom oct 26 22:11:03 ART 2003
22 // Autores: Leandro Lucarella <llucare@fi.uba.ar>
23 //----------------------------------------------------------------------------
24 //
25 // $Id$
26 //
27
28 #include "plaqui/server/httprequest.h"
29 #include "plaqui/server/string.h"
30 #ifdef DEBUG
31 #       include <iostream>
32 #endif // DEBUG
33
34 using namespace std;
35
36 namespace PlaQui {
37
38 namespace Server {
39
40 HTTPRequest::~HTTPRequest(void) {
41 #ifdef DEBUG
42         cerr << __FILE__ << ": destructor." << endl;
43 #endif // DEBUG
44 }
45
46 HTTPRequest::HTTPRequest(const string& uri, const HTTPMethod& method,
47                 const string& query, const string& body, const string& version):
48                 HTTPMessage(body, version), method(method), uri(uri), query(query) {
49 #ifdef DEBUG
50         cerr << __FILE__ << ": uri = " << uri << " | "
51                         << "method = " << method_str() << " | "
52                         << "query = " << query << " | "
53                         << "body.length = " << body.length() << " | "
54                         << "version = " << version << endl;
55 #endif // DEBUG
56 }
57
58 string HTTPRequest::method_str(void) const {
59         switch (method) {
60                 case POST:
61                         return "POST";
62                 case GET:
63                 default:
64                         return "GET";
65         }
66 }
67
68 istream& operator>>(istream& is, HTTPRequest& req)
69                 throw(HTTPError, ios::failure) {
70 #ifdef DEBUG
71         cerr << __FILE__ << ": operator>>()" << endl;
72 #endif // DEBUG
73         char buf[BUFSIZ];
74         // Obtengo primera línea (request)
75         if (!is.getline(buf, BUFSIZ)) {
76                 // No hay más líneas.
77                 throw ios::failure("socket closed");
78         }
79 #ifdef DEBUG
80         cerr << __FILE__ << ":\tRecibiendo linea: " << buf << endl;
81 #endif // DEBUG
82         String line(buf);
83         // Si es la primera línea, es el request.
84         if (line.length() < 3) {
85                 throw HTTPError(HTTPMessage::BAD_REQUEST, line
86                                 + ": No tiene un método conocido.");
87         }
88         // Averiguo método.
89         string::size_type pos = line.find_first_of(String::SPACE_CHARS);
90         String met = line.substr(0, pos); 
91         met.to_upper();
92         if (met == "GET") {
93                 req.method = HTTPRequest::GET;
94         } else if (met == "POST") {
95                 req.method = HTTPRequest::POST;
96         } else {
97                 throw HTTPError(HTTPMessage::NOT_IMPLEMENTED, met
98                                 + ": No es un método soportado.");
99         }
100         // Si tiene sólo el método, no es válido.
101         line = line.substr(pos + 1);
102         line.trim();
103         if (!line.length()) {
104                 throw HTTPError(HTTPMessage::BAD_REQUEST, "Falta URI.");
105         }
106         // Si tiene más espacios, tengo la URI y el protocolo (o un error).
107         pos = line.find_first_of(String::SPACE_CHARS);
108         if (pos != string::npos) {
109                 // Si el resto es un protocolo válido, agrego más variables.
110                 String protocol = line.substr(pos + 1);
111                 protocol = protocol.trim().to_upper();
112                 if (protocol.substr(0, 5) != "HTTP/") {
113                         throw HTTPError(HTTPMessage::BAD_REQUEST,
114                                         protocol + ": Protocolo desconocido");
115                 }
116                 if (protocol.substr(5) == "1.0") {
117                         req.version = "1.0";
118                 } else if (protocol.substr(5) == "1.1") {
119                         req.version = "1.1";
120                 // Si no es un error.
121                 } else {
122                         throw HTTPError(HTTPMessage::HTTP_VERSION_NOT_SUPPORTED,
123                                         protocol.substr(5) + ": Versión HTTP no soportada.");
124                 }
125                 line = line.substr(0, pos);
126         }
127         // Agrego la URI y sus derivados.
128         if (!line.length() || (line[0] != '/')) {
129                         // FIXME || request.find_first_not_of(";/?:@&=+$,")) {
130                 throw HTTPError(HTTPMessage::BAD_REQUEST,
131                                 line + ": La URI no comienza con /.");
132         }
133         // Si tiene un query string.
134         pos = line.find("?");
135         if (pos != string::npos) {
136                 req.query = line.substr(pos + 1);
137         } else {
138                 req.query  = "";
139         }
140         req.uri = line.substr(0, pos);
141         // Fin de request, obtengo el mensaje.
142         is >> static_cast<HTTPMessage&>(req);
143         //PlaQui::Server::operator>>(is, static_cast<HTTPMessage>(req));
144         return is;
145 }
146
147 ostream& operator<<(ostream& os, const HTTPRequest& req) {
148 #ifdef DEBUG
149         cerr << __FILE__ << ": operator<<()" << endl;
150 #endif // DEBUG
151         os << req.method_str() << " " << req.uri;
152         if (req.query.length()) {
153                 os << "?" << req.query;
154         }
155         os << " HTTP/" << req.version << "\r\n"
156                 << static_cast<const HTTPMessage&>(req);
157         return os;
158 }
159
160 } // namespace Server
161
162 } // namespace PlaQui
163