diff --git a/client/port.cpp b/client/port.cpp
index 8d99cfd..90992ab 100644
--- a/client/port.cpp
+++ b/client/port.cpp
@@ -19,9 +19,7 @@ along with this program. If not, see
#include "port.h"
-#include "fileformat.h"
-#include "pcapfileformat.h"
-#include "pdmlfileformat.h"
+#include "abstractfileformat.h"
#include
#include
@@ -228,10 +226,12 @@ void Port::updateStats(OstProto::PortStats *portStats)
bool Port::openStreams(QString fileName, bool append, QString &error)
{
OstProto::StreamConfigList streams;
+ AbstractFileFormat *fmt = AbstractFileFormat::fileFormatFromFile(fileName);
- //if (!fileFormat.openStreams(fileName, streams, error))
- //if (!pdmlFileFormat.openStreams(fileName, streams, error))
- if (!pcapFileFormat.openStreams(fileName, streams, error))
+ if (fmt == NULL)
+ goto _fail;
+
+ if (!fmt->openStreams(fileName, streams, error))
goto _fail;
if (!append)
@@ -253,10 +253,14 @@ _fail:
return false;
}
-bool Port::saveStreams(QString fileName, QString &error)
+bool Port::saveStreams(QString fileName, QString fileType, QString &error)
{
+ AbstractFileFormat *fmt = AbstractFileFormat::fileFormatFromType(fileType);
OstProto::StreamConfigList streams;
+ if (fmt == NULL)
+ goto _fail;
+
streams.mutable_port_id()->set_id(0);
for (int i = 0; i < mStreams.size(); i++)
{
@@ -264,6 +268,9 @@ bool Port::saveStreams(QString fileName, QString &error)
mStreams[i]->protoDataCopyInto(*s);
}
- //return fileFormat.saveStreams(streams, fileName, error);
- return pcapFileFormat.saveStreams(streams, fileName, error);
+ return fmt->saveStreams(streams, fileName, error);
+
+_fail:
+ error = QString("Unsupported File Type - %1").arg(fileType);
+ return false;
}
diff --git a/client/port.h b/client/port.h
index 2fbb9a0..275ea61 100644
--- a/client/port.h
+++ b/client/port.h
@@ -119,7 +119,7 @@ public:
void updateStats(OstProto::PortStats *portStats);
bool openStreams(QString fileName, bool append, QString &error);
- bool saveStreams(QString fileName, QString &error);
+ bool saveStreams(QString fileName, QString fileType, QString &error);
signals:
void portDataChanged(int portGroupId, int portId);
diff --git a/client/portswindow.cpp b/client/portswindow.cpp
index 58070a0..86bcf71 100644
--- a/client/portswindow.cpp
+++ b/client/portswindow.cpp
@@ -19,13 +19,14 @@ along with this program. If not, see
#include "portswindow.h"
+#include "abstractfileformat.h"
+#include "streamconfigdialog.h"
+#include "streamlistdelegate.h"
+
#include
#include
#include
-#include "streamconfigdialog.h"
-#include "streamlistdelegate.h"
-
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
: QWidget(parent)
{
@@ -497,17 +498,44 @@ void PortsWindow::on_actionSave_Streams_triggered()
QModelIndex current = tvPortList->selectionModel()->currentIndex();
QString fileName;
+ QStringList fileTypes = AbstractFileFormat::supportedFileTypes();
+ QString fileType;
QString errorStr;
+ QFileDialog::Options options;
+
+ // On Mac OS with Native Dialog, getSaveFileName() ignores fileType
+ // which we need.
+#ifdef Q_OS_MAC
+ options |= QFileDialog::DontUseNativeDialog;
+#endif
+
+ if (fileTypes.size())
+ fileType = fileTypes.at(0);
Q_ASSERT(plm->isPort(current));
- fileName = QFileDialog::getSaveFileName(this, tr("Save Streams"));
+_retry:
+ fileName = QFileDialog::getSaveFileName(this, tr("Save Streams"),
+ fileName, fileTypes.join(";;"), &fileType, options);
if (fileName.isEmpty())
goto _exit;
+ fileType = fileType.remove(QRegExp("\\(.*\\)")).trimmed();
+ if (!fileType.startsWith("Ostinato"))
+ {
+ if (QMessageBox::warning(this, tr("Ostinato"),
+ QString("You have chosen to save in %1 format. All stream "
+ "attributes may not be saved in this format.\n\n"
+ "It is recommended to save in native Ostinato format.\n\n"
+ "Continue to save in %2 format?").arg(fileType).arg(fileType),
+ QMessageBox::Yes|QMessageBox::No,
+ QMessageBox::No) != QMessageBox::Yes)
+ goto _retry;
+ }
+
// TODO: all or selected?
- if (!plm->port(current).saveStreams(fileName, errorStr))
+ if (!plm->port(current).saveStreams(fileName, fileType, errorStr))
QMessageBox::critical(this, qApp->applicationName(), errorStr);
else if (!errorStr.isEmpty())
QMessageBox::warning(this, qApp->applicationName(), errorStr);
diff --git a/common/abstractfileformat.cpp b/common/abstractfileformat.cpp
new file mode 100644
index 0000000..cb3fa43
--- /dev/null
+++ b/common/abstractfileformat.cpp
@@ -0,0 +1,73 @@
+/*
+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 "abstractfileformat.h"
+
+#include "fileformat.h"
+#include "pcapfileformat.h"
+#include "pdmlfileformat.h"
+
+#include
+
+AbstractFileFormat::AbstractFileFormat()
+{
+}
+
+AbstractFileFormat::~AbstractFileFormat()
+{
+}
+
+QStringList AbstractFileFormat::supportedFileTypes()
+{
+ return QStringList()
+ << "Ostinato (*)"
+ << "PCAP (*)"
+ << "PDML (*.pdml)";
+}
+AbstractFileFormat* AbstractFileFormat::fileFormatFromFile(
+ const QString fileName)
+{
+
+ if (fileFormat.isMyFileFormat(fileName))
+ return &fileFormat;
+
+ if (pdmlFileFormat.isMyFileFormat(fileName))
+ return &pdmlFileFormat;
+
+ if (pcapFileFormat.isMyFileFormat(fileName))
+ return &pcapFileFormat;
+
+ return NULL;
+}
+
+AbstractFileFormat* AbstractFileFormat::fileFormatFromType(
+ const QString fileType)
+{
+
+ if (fileFormat.isMyFileType(fileType))
+ return &fileFormat;
+
+ if (pdmlFileFormat.isMyFileType(fileType))
+ return &pdmlFileFormat;
+
+ if (pcapFileFormat.isMyFileType(fileType))
+ return &pcapFileFormat;
+
+ return NULL;
+}
diff --git a/common/abstractfileformat.h b/common/abstractfileformat.h
new file mode 100644
index 0000000..7a648ee
--- /dev/null
+++ b/common/abstractfileformat.h
@@ -0,0 +1,52 @@
+/*
+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
+*/
+
+#ifndef _ABSTRACT_FILE_FORMAT_H
+#define _ABSTRACT_FILE_FORMAT_H
+
+#include "protocol.pb.h"
+
+#include
+#include
+
+class AbstractFileFormat : public QObject
+{
+ Q_OBJECT
+public:
+ AbstractFileFormat();
+ virtual ~AbstractFileFormat();
+
+ virtual bool openStreams(const QString fileName,
+ OstProto::StreamConfigList &streams, QString &error) = 0;
+ virtual bool saveStreams(const OstProto::StreamConfigList streams,
+ const QString fileName, QString &error) = 0;
+
+ static AbstractFileFormat* fileFormatFromFile(const QString fileName);
+ static AbstractFileFormat* fileFormatFromType(const QString fileType);
+
+ static QStringList supportedFileTypes();
+
+#if 0
+ bool isMyFileFormat(const QString fileName) = 0;
+ bool isMyFileType(const QString fileType) = 0;
+#endif
+};
+
+#endif
+
diff --git a/common/fileformat.cpp b/common/fileformat.cpp
index 619ab37..7ddc65b 100644
--- a/common/fileformat.cpp
+++ b/common/fileformat.cpp
@@ -394,6 +394,38 @@ _fail:
return false;
}
+bool FileFormat::isMyFileFormat(const QString fileName)
+{
+ bool ret = false;
+ QFile file(fileName);
+ QByteArray buf;
+ OstProto::FileMagic magic;
+
+ if (!file.open(QIODevice::ReadOnly))
+ goto _exit;
+
+ buf = file.peek(kFileMagicOffset + kFileMagicSize);
+ if (!magic.ParseFromArray((void*)(buf.constData() + kFileMagicOffset),
+ kFileMagicSize))
+ goto _close_exit;
+
+ if (magic.value() == kFileMagicValue)
+ ret = true;
+
+_close_exit:
+ file.close();
+_exit:
+ return ret;
+}
+
+bool FileFormat::isMyFileType(const QString fileType)
+{
+ if (fileType.startsWith("Ostinato"))
+ return true;
+ else
+ return false;
+}
+
void FileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
{
// Fill in the "native" file format version
diff --git a/common/fileformat.h b/common/fileformat.h
index ebdc97c..0204906 100644
--- a/common/fileformat.h
+++ b/common/fileformat.h
@@ -19,24 +19,27 @@ along with this program. If not, see
#ifndef _FILE_FORMAT_H
#define _FILE_FORMAT_H
+#include "abstractfileformat.h"
+
#include "fileformat.pb.h"
-#include
-#include
-
-class FileFormat : public QObject
+class FileFormat : public AbstractFileFormat
{
- Q_OBJECT
public:
FileFormat();
~FileFormat();
- bool openStreams(const QString fileName,
+ virtual bool openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error);
- bool saveStreams(const OstProto::StreamConfigList streams,
+ virtual bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error);
+ bool isMyFileFormat(const QString fileName);
+ bool isMyFileType(const QString fileType);
+
private:
+ void initFileMetaData(OstProto::FileMetaData &metaData);
+
static const int kFileMagicSize = 12;
static const int kFileChecksumSize = 5;
static const int kFileMinSize = kFileMagicSize + kFileChecksumSize;
@@ -50,8 +53,6 @@ private:
static const uint kFileFormatVersionMajor = 0;
static const uint kFileFormatVersionMinor = 1;
static const uint kFileFormatVersionRevision = 3;
-
- void initFileMetaData(OstProto::FileMetaData &metaData);
};
extern FileFormat fileFormat;
diff --git a/common/ostproto.pro b/common/ostproto.pro
index ef829da..3283090 100644
--- a/common/ostproto.pro
+++ b/common/ostproto.pro
@@ -57,6 +57,7 @@ PROTOS += \
HEADERS += \
abstractprotocol.h \
comboprotocol.h \
+ abstractfileformat.h \
fileformat.h \
pcapfileformat.h \
pdmlfileformat.h \
@@ -98,6 +99,7 @@ HEADERS += \
SOURCES += \
abstractprotocol.cpp \
crc32c.cpp \
+ abstractfileformat.cpp \
fileformat.cpp \
pcapfileformat.cpp \
pdmlfileformat.cpp \
diff --git a/common/pcapfileformat.cpp b/common/pcapfileformat.cpp
index 967c565..a893565 100644
--- a/common/pcapfileformat.cpp
+++ b/common/pcapfileformat.cpp
@@ -25,6 +25,7 @@ along with this program. If not, see
#include
#include
+#include
#include
#include
#include
@@ -243,7 +244,7 @@ _non_pdml:
_err_unsupported_encap:
error = QString(tr("%1 has non-ethernet encapsulation (%2) which is "
"not supported - Sorry!"))
- .arg(fileName).arg(fileHdr.network);
+ .arg(QFileInfo(fileName).fileName()).arg(fileHdr.network);
goto _exit;
#endif
@@ -391,3 +392,16 @@ _exit:
return isOk;
}
+bool PcapFileFormat::isMyFileFormat(const QString fileName)
+{
+ // TODO
+ return true;
+}
+
+bool PcapFileFormat::isMyFileType(const QString fileType)
+{
+ if (fileType.startsWith("PCAP"))
+ return true;
+ else
+ return false;
+}
diff --git a/common/pcapfileformat.h b/common/pcapfileformat.h
index 04a02ec..4f7ab7a 100644
--- a/common/pcapfileformat.h
+++ b/common/pcapfileformat.h
@@ -19,16 +19,13 @@ along with this program. If not, see
#ifndef _PCAP_FILE_FORMAT_H
#define _PCAP_FILE_FORMAT_H
-#include "protocol.pb.h"
+#include "abstractfileformat.h"
#include
-#include
class PdmlReader;
-class PcapFileFormat : public QObject
+class PcapFileFormat : public AbstractFileFormat
{
- Q_OBJECT
-
friend class PdmlReader;
public:
@@ -40,6 +37,9 @@ public:
bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error);
+ bool isMyFileFormat(const QString fileName);
+ bool isMyFileType(const QString fileType);
+
private:
typedef struct {
quint32 magicNumber; /* magic number */
diff --git a/common/pdmlfileformat.cpp b/common/pdmlfileformat.cpp
index 3f86084..0c51652 100644
--- a/common/pdmlfileformat.cpp
+++ b/common/pdmlfileformat.cpp
@@ -92,6 +92,43 @@ _exit:
bool PdmlFileFormat::saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error)
{
+ error = "Save to PDML format is not supported";
return false;
}
+bool PdmlFileFormat::isMyFileFormat(const QString fileName)
+{
+ bool ret = false;
+ QFile file(fileName);
+ QByteArray buf;
+ QXmlStreamReader xml;
+
+ if (!file.open(QIODevice::ReadOnly))
+ goto _exit;
+
+ xml.setDevice(&file);
+
+ xml.readNext();
+ if (xml.hasError() || !xml.isStartDocument())
+ goto _close_exit;
+
+ xml.readNext();
+ if (!xml.hasError() && xml.isStartElement() && (xml.name() == "pdml"))
+ ret = true;
+ else
+ ret = false;
+
+_close_exit:
+ xml.clear();
+ file.close();
+_exit:
+ return ret;
+}
+
+bool PdmlFileFormat::isMyFileType(const QString fileType)
+{
+ if (fileType.startsWith("PDML"))
+ return true;
+ else
+ return false;
+}
diff --git a/common/pdmlfileformat.h b/common/pdmlfileformat.h
index d392c6b..e05026a 100644
--- a/common/pdmlfileformat.h
+++ b/common/pdmlfileformat.h
@@ -19,24 +19,22 @@ along with this program. If not, see
#ifndef _PDML_FILE_FORMAT_H
#define _PDML_FILE_FORMAT_H
-#include "protocol.pb.h"
+#include "abstractfileformat.h"
-#include
-
-class PdmlParser;
-
-class PdmlFileFormat : public QObject
+class PdmlFileFormat : public AbstractFileFormat
{
- Q_OBJECT
-
public:
PdmlFileFormat();
~PdmlFileFormat();
- bool openStreams(const QString fileName,
+ virtual bool openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error);
- bool saveStreams(const OstProto::StreamConfigList streams,
+ virtual bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error);
+
+ bool isMyFileFormat(const QString fileName);
+ bool isMyFileType(const QString fileType);
+
};
extern PdmlFileFormat pdmlFileFormat;