/* Copyright (C) 2011 Srivats P. This file is part of "Ostinato" This 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 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ #include "textprotopdml.h" #include "textproto.pb.h" PdmlTextProtocol::PdmlTextProtocol() { ostProtoId_ = OstProto::Protocol::kTextProtocolFieldNumber; } PdmlProtocol* PdmlTextProtocol::createInstance() { return new PdmlTextProtocol(); } void PdmlTextProtocol::preProtocolHandler(QString /*name*/, const QXmlStreamAttributes &attributes, int expectedPos, OstProto::Protocol *pbProto, OstProto::Stream *stream) { bool isOk; int size; int pos = attributes.value("pos").toString().toUInt(&isOk); if (!isOk) { if (expectedPos >= 0) expPos_ = pos = expectedPos; else goto _skip_pos_size_proc; } size = attributes.value("size").toString().toUInt(&isOk); if (!isOk) goto _skip_pos_size_proc; // If pos+size goes beyond the frame length, this is a "reassembled" // protocol and should be skipped if ((pos + size) > int(stream->core().frame_len())) goto _skip_pos_size_proc; expPos_ = pos; endPos_ = expPos_ + size; _skip_pos_size_proc: qDebug("expPos_ = %d, endPos_ = %d", expPos_, endPos_); OstProto::TextProtocol *text = pbProto->MutableExtension( OstProto::textProtocol); text->set_port_num(0); text->set_eol(OstProto::TextProtocol::kCrLf); // by default we assume CRLF detectEol_ = true; contentType_ = kUnknownContent; } void PdmlTextProtocol::unknownFieldHandler(QString name, int pos, int size, const QXmlStreamAttributes &attributes, OstProto::Protocol *pbProto, OstProto::Stream* /*stream*/) { if (name == "http.file_data") // ignore as it's dup of other fields return; _retry: switch(contentType_) { case kUnknownContent: if (name == "data") contentType_ = kOtherContent; else contentType_ = kTextContent; goto _retry; break; case kTextContent: { OstProto::TextProtocol *text = pbProto->MutableExtension( OstProto::textProtocol); if ((name == "data") || (attributes.value("show") == "HTTP chunked response")) { contentType_ = kOtherContent; goto _retry; } QByteArray line = QByteArray::fromHex( attributes.value("value").toString().toUtf8()); foreach(char c, line) { if (!isprint(c) && !isspace(c)) { contentType_ = kOtherContent; goto _retry; } } if (pos < expPos_) break; if ((pos + size) > endPos_) break; if (pos > expPos_) { int gap = pos - expPos_; QByteArray filler(gap, '\n'); if (text->eol() == OstProto::TextProtocol::kCrLf) { if (gap & 0x01) // Odd { filler.resize(gap/2 + 1); filler[0]=int(' '); } else // Even filler.resize(gap/2); } text->mutable_text()->append(filler.constData(), filler.size()); expPos_ += gap; } if (detectEol_) { if (line.right(2) == "\r\n") text->set_eol(OstProto::TextProtocol::kCrLf); else if (line.right(1) == "\r") text->set_eol(OstProto::TextProtocol::kCr); else if (line.right(1) == "\n") text->set_eol(OstProto::TextProtocol::kLf); detectEol_ = false; } // Convert line endings to LF only - Qt reqmt that TextProto honours line.replace("\r\n", "\n"); line.replace('\r', '\n'); text->mutable_text()->append(line.constData(), line.size()); expPos_ += size; break; } case kOtherContent: // Do nothing! break; default: Q_ASSERT(false); } } void PdmlTextProtocol::postProtocolHandler(OstProto::Protocol *pbProto, OstProto::Stream *stream) { OstProto::TextProtocol *text = pbProto->MutableExtension( OstProto::textProtocol); // Empty Text Content - remove ourselves if (text->text().length() == 0) stream->mutable_protocol()->RemoveLast(); expPos_ = endPos_ = -1; detectEol_ = true; contentType_ = kUnknownContent; }