ostinato/common/textprotopdml.cpp

181 lines
4.9 KiB
C++

/*
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 <http://www.gnu.org/licenses/>
*/
#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;
}