Removed legacy libraries (converter, ftp, filesystem) from codebase.

This commit is contained in:
Thulinma 2015-04-15 14:24:43 +02:00
parent 73b1f2d75c
commit 7c0db4531d
7 changed files with 0 additions and 1393 deletions

View file

@ -92,12 +92,9 @@ set(libHeaders
${SOURCE_DIR}/lib/bitstream.h
${SOURCE_DIR}/lib/checksum.h
${SOURCE_DIR}/lib/config.h
${SOURCE_DIR}/lib/converter.h
${SOURCE_DIR}/lib/defines.h
${SOURCE_DIR}/lib/dtsc.h
${SOURCE_DIR}/lib/filesystem.h
${SOURCE_DIR}/lib/flv_tag.h
${SOURCE_DIR}/lib/ftp.h
${SOURCE_DIR}/lib/http_parser.h
${SOURCE_DIR}/lib/json.h
${SOURCE_DIR}/lib/mp4_adobe.h
@ -128,12 +125,9 @@ set(libSources
${SOURCE_DIR}/lib/bitfields.cpp
${SOURCE_DIR}/lib/bitstream.cpp
${SOURCE_DIR}/lib/config.cpp
${SOURCE_DIR}/lib/converter.cpp
${SOURCE_DIR}/lib/dtsc.cpp
${SOURCE_DIR}/lib/dtscmeta.cpp
${SOURCE_DIR}/lib/filesystem.cpp
${SOURCE_DIR}/lib/flv_tag.cpp
${SOURCE_DIR}/lib/ftp.cpp
${SOURCE_DIR}/lib/http_parser.cpp
${SOURCE_DIR}/lib/json.cpp
${SOURCE_DIR}/lib/mp4_adobe.cpp

View file

@ -1,328 +0,0 @@
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sstream>
#include "timing.h"
#include "converter.h"
#include "procs.h"
#include "config.h"
namespace Converter {
///\brief The base constructor
Converter::Converter() {
fillFFMpegEncoders();
}
///\brief A function that fill the internal variables with values provided by examing ffmpeg output
///
///Checks for the following encoders:
/// - AAC
/// - H264
/// - MP3
void Converter::fillFFMpegEncoders() {
std::vector<char *> cmd;
cmd.reserve(3);
cmd.push_back((char *)"ffmpeg");
cmd.push_back((char *)"-encoders");
cmd.push_back(NULL);
int outFD = -1;
Util::Procs::StartPiped("FFMpegInfo", &cmd[0], 0, &outFD, 0);
while (Util::Procs::isActive("FFMpegInfo")) {
Util::sleep(100);
}
FILE * outFile = fdopen(outFD, "r");
char * fileBuf = 0;
size_t fileBufLen = 0;
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)) {
if (strstr(fileBuf, "aac") || strstr(fileBuf, "AAC")) {
strtok(fileBuf, " \t");
allCodecs["ffmpeg"][strtok(NULL, " \t")] = "aac";
}
if (strstr(fileBuf, "h264") || strstr(fileBuf, "H264")) {
strtok(fileBuf, " \t");
allCodecs["ffmpeg"][strtok(NULL, " \t")] = "h264";
}
if (strstr(fileBuf, "mp3") || strstr(fileBuf, "MP3")) {
strtok(fileBuf, " \t");
allCodecs["ffmpeg"][strtok(NULL, " \t")] = "mp3";
}
}
fclose(outFile);
}
///\brief A function to obtain all available codecs that have been obtained from the encoders.
///\return A reference to the allCodecs member.
converterInfo & Converter::getCodecs() {
return allCodecs;
}
///\brief A function to obtain the available encoders in JSON format.
///\return A JSON::Value containing all encoder:codec pairs.
JSON::Value Converter::getEncoders() {
JSON::Value result;
for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++) {
for (codecInfo::iterator codIt = convIt->second.begin(); codIt != convIt->second.end(); codIt++) {
if (codIt->second == "h264") {
result[convIt->first]["video"][codIt->first] = codIt->second;
} else {
result[convIt->first]["audio"][codIt->first] = codIt->second;
}
}
}
return result;
}
///\brief Looks in a given path for all files that could be converted
///\param myPath The location to look at, this should be a folder.
///\return A JSON::Value containing all media files in the location, with their corresponding metadata values.
JSON::Value Converter::queryPath(std::string myPath) {
char const * cmd[3] = {0, 0, 0};
std::string mistPath = Util::getMyPath() + "MistInfo";
cmd[0] = mistPath.c_str();
JSON::Value result;
DIR * Dirp = opendir(myPath.c_str());
struct stat StatBuf;
if (Dirp) {
dirent * entry;
while ((entry = readdir(Dirp))) {
if (stat(std::string(myPath + "/" + entry->d_name).c_str(), &StatBuf) == -1) {
continue;
}
if ((StatBuf.st_mode & S_IFREG) == 0) {
continue;
}
std::string fileName = entry->d_name;
std::string mijnPad = std::string(myPath + (myPath[myPath.size() - 1] == '/' ? "" : "/") + entry->d_name);
cmd[1] = mijnPad.c_str();
result[fileName] = JSON::fromString(Util::Procs::getOutputOf((char * const *)cmd));
}
}
return result;
}
///\brief Start a conversion with the given parameters
///\param name The name to use for logging the conversion.
///\param parameters The parameters, accepted are the following:
/// - input The input url
/// - output The output url
/// - encoder The encoder to use
/// - video An object containing video parameters, if not existant no video will be output. Values are:
/// - width The width of the resulting video
/// - height The height of the resulting video
/// - codec The codec to encode video in, or copy to use the current codec
/// - fpks The framerate in fps * 1000
/// - audio An object containing audio parameters, if not existant no audio will be output. Values are:
/// - codec The codec to encode audio in, or copy to use the current codec
/// - samplerate The target samplerate for the audio, in hz
void Converter::startConversion(std::string name, JSON::Value parameters) {
if (!parameters.isMember("input")) {
statusHistory[name] = "No input file supplied";
return;
}
if (!parameters.isMember("output")) {
statusHistory[name] = "No output file supplied";
return;
}
struct stat statBuf;
std::string outPath = parameters["output"].asString();
outPath = outPath.substr(0, outPath.rfind('/'));
int statRes = stat(outPath.c_str(), & statBuf);
if (statRes == -1 || !S_ISDIR(statBuf.st_mode)) {
statusHistory[name] = "Output path is either non-existent, or not a path.";
return;
}
if (!parameters.isMember("encoder")) {
statusHistory[name] = "No encoder specified";
return;
}
if (allCodecs.find(parameters["encoder"]) == allCodecs.end()) {
statusHistory[name] = "Can not find encoder " + parameters["encoder"].asString();
return;
}
if (parameters.isMember("video")) {
if (parameters["video"].isMember("width") && !parameters["video"].isMember("height")) {
statusHistory[name] = "No height parameter given";
return;
}
if (parameters["video"].isMember("height") && !parameters["video"].isMember("width")) {
statusHistory[name] = "No width parameter given";
return;
}
}
std::stringstream encoderCommand;
if (parameters["encoder"] == "ffmpeg") {
encoderCommand << "ffmpeg -i ";
encoderCommand << parameters["input"].asString() << " ";
if (parameters.isMember("video")) {
if (!parameters["video"].isMember("codec") || parameters["video"]["codec"] == "copy") {
encoderCommand << "-vcodec copy ";
} else {
codecInfo::iterator vidCodec = allCodecs["ffmpeg"].find(parameters["video"]["codec"]);
if (vidCodec == allCodecs["ffmpeg"].end()) {
statusHistory[name] = "Can not find video codec " + parameters["video"]["codec"].asString();
return;
}
encoderCommand << "-vcodec " << vidCodec->first << " ";
if (parameters["video"]["codec"].asString() == "h264") {
//Enforce baseline
encoderCommand << "-preset slow -profile:v baseline -level 30 ";
}
if (parameters["video"].isMember("fpks")) {
encoderCommand << "-r " << parameters["video"]["fpks"].asInt() / 1000 << " ";
}
if (parameters["video"].isMember("width")) {
encoderCommand << "-s " << parameters["video"]["width"].asInt() << "x" << parameters["video"]["height"].asInt() << " ";
}
///\todo Keyframe interval (different in older and newer versions of ffmpeg?)
}
} else {
encoderCommand << "-vn ";
}
if (parameters.isMember("audio")) {
if (!parameters["audio"].isMember("codec")) {
encoderCommand << "-acodec copy ";
} else {
codecInfo::iterator audCodec = allCodecs["ffmpeg"].find(parameters["audio"]["codec"]);
if (audCodec == allCodecs["ffmpeg"].end()) {
statusHistory[name] = "Can not find audio codec " + parameters["audio"]["codec"].asString();
return;
}
if (audCodec->second == "aac") {
encoderCommand << "-strict -2 ";
}
encoderCommand << "-acodec " << audCodec->first << " ";
if (parameters["audio"].isMember("samplerate")) {
encoderCommand << "-ar " << parameters["audio"]["samplerate"].asInt() << " ";
}
}
} else {
encoderCommand << "-an ";
}
encoderCommand << "-f flv -";
}
int statusFD = -1;
Util::Procs::StartPiped2(name, encoderCommand.str(), Util::getMyPath() + "MistFLV2DTSC -o " + parameters["output"].asString(), 0, 0, &statusFD, 0);
parameters["statusFD"] = statusFD;
allConversions[name] = parameters;
allConversions[name]["status"]["duration"] = "?";
allConversions[name]["status"]["progress"] = 0;
allConversions[name]["status"]["frame"] = 0;
allConversions[name]["status"]["time"] = 0;
}
///\brief Updates the internal status of the converter class.
///
///Will check for each running conversion whether it is still running, and update its status accordingly
void Converter::updateStatus() {
if (allConversions.size()) {
std::map<std::string, JSON::Value>::iterator cIt;
bool hasChanged = true;
while (hasChanged && allConversions.size()) {
hasChanged = false;
for (cIt = allConversions.begin(); cIt != allConversions.end(); cIt++) {
if (Util::Procs::isActive(cIt->first)) {
int statusFD = dup(cIt->second["statusFD"].asInt());
fsync(statusFD);
FILE * statusFile = fdopen(statusFD, "r");
char * fileBuf = 0;
size_t fileBufLen = 0;
fseek(statusFile, 0, SEEK_END);
std::string line;
int totalTime = 0;
do {
getdelim(&fileBuf, &fileBufLen, '\r', statusFile);
line = fileBuf;
if (line.find("Duration") != std::string::npos) {
int curOffset = line.find("Duration: ") + 10;
totalTime += atoi(line.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
totalTime += atoi(line.substr(curOffset + 3, 2).c_str()) * 60 * 1000;
totalTime += atoi(line.substr(curOffset + 6, 2).c_str()) * 1000;
totalTime += atoi(line.substr(curOffset + 9, 2).c_str()) * 10;
cIt->second["duration"] = totalTime;
}
} while (!feof(statusFile) && line.find("frame") != 0); //"frame" is the fist word on an actual status line of ffmpeg
if (!feof(statusFile)) {
cIt->second["status"] = parseFFMpegStatus(line);
cIt->second["status"]["duration"] = cIt->second["duration"];
cIt->second["status"]["progress"] = (cIt->second["status"]["time"].asInt() * 100) / cIt->second["duration"].asInt();
} else {
line.erase(line.end() - 1);
line = line.substr(line.rfind("\n") + 1);
cIt->second["status"] = line;
}
free(fileBuf);
fclose(statusFile);
} else {
if (statusHistory.find(cIt->first) == statusHistory.end()) {
statusHistory[cIt->first] = "Conversion successful, running DTSCFix";
Util::Procs::Start(cIt->first + "DTSCFix", Util::getMyPath() + "MistDTSCFix " + cIt->second["output"].asString());
}
allConversions.erase(cIt);
hasChanged = true;
break;
}
}
}
}
if (statusHistory.size()) {
std::map<std::string, std::string>::iterator sIt;
for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++) {
if (statusHistory[sIt->first].find("DTSCFix") != std::string::npos) {
if (Util::Procs::isActive(sIt->first + "DTSCFIX")) {
continue;
}
statusHistory[sIt->first] = "Conversion successful";
}
}
}
}
///\brief Parses a single ffmpeg status line into a JSON format
///\param statusLine The current status of ffmpeg
///\return A JSON::Value with the following values set:
/// - frame The current last encoded frame
/// - time The current last encoded timestamp
JSON::Value Converter::parseFFMpegStatus(std::string statusLine) {
JSON::Value result;
int curOffset = statusLine.find("frame=") + 6;
result["frame"] = atoi(statusLine.substr(curOffset, statusLine.find("fps=") - curOffset).c_str());
curOffset = statusLine.find("time=") + 5;
int myTime = 0;
myTime += atoi(statusLine.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
myTime += atoi(statusLine.substr(curOffset + 3, 2).c_str()) * 60 * 1000;
myTime += atoi(statusLine.substr(curOffset + 6, 2).c_str()) * 1000;
myTime += atoi(statusLine.substr(curOffset + 9, 2).c_str()) * 10;
result["time"] = myTime;
return result;
}
///\brief Obtain the current internal status of the conversion class
///\return A JSON::Value with the status of each conversion
JSON::Value Converter::getStatus() {
updateStatus();
JSON::Value result;
if (allConversions.size()) {
for (std::map<std::string, JSON::Value>::iterator cIt = allConversions.begin(); cIt != allConversions.end(); cIt++) {
result[cIt->first] = cIt->second["status"];
result[cIt->first]["details"] = cIt->second;
}
}
if (statusHistory.size()) {
std::map<std::string, std::string>::iterator sIt;
for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++) {
result[sIt->first] = sIt->second;
}
}
return result;
}
///\brief Clears the status history of all conversions
void Converter::clearStatus() {
statusHistory.clear();
}
}

View file

@ -1,35 +0,0 @@
#include <map>
#include <string>
#include "json.h"
///\brief A typedef to simplify accessing all codecs
typedef std::map<std::string, std::string> codecInfo;
///\brief A typedef to simplify accessing all encoders
typedef std::map<std::string, codecInfo> converterInfo;
///\brief A namespace containing all functions for handling the conversion API
namespace Converter {
///\brief A class containing the basic conversion API functionality
class Converter {
public:
Converter();
converterInfo & getCodecs();
JSON::Value getEncoders();
JSON::Value queryPath(std::string myPath);
void startConversion(std::string name, JSON::Value parameters);
void updateStatus();
JSON::Value getStatus();
void clearStatus();
JSON::Value parseFFMpegStatus(std::string statusLine);
private:
void fillFFMpegEncoders();
///\brief Holds a list of all current known codecs
converterInfo allCodecs;
///\brief Holds a list of all the current conversions
std::map<std::string, JSON::Value> allConversions;
///\brief Stores the status of all conversions, and the history
std::map<std::string, std::string> statusHistory;
};
}

View file

@ -1,318 +0,0 @@
#include "filesystem.h"
#include "defines.h"
Filesystem::Directory::Directory(std::string PathName, std::string BasePath) {
MyBase = BasePath;
if (PathName[0] == '/') {
PathName.erase(0, 1);
}
if (BasePath[BasePath.size() - 1] != '/') {
BasePath += "/";
}
MyPath = PathName;
FillEntries();
}
Filesystem::Directory::~Directory() {
}
void Filesystem::Directory::FillEntries() {
ValidDir = true;
struct stat StatBuf;
Entries.clear();
DIR * Dirp = opendir((MyBase + MyPath).c_str());
if (!Dirp) {
ValidDir = false;
} else {
dirent * entry;
while ((entry = readdir(Dirp))) {
if (stat((MyBase + MyPath + "/" + entry->d_name).c_str(), &StatBuf) == -1) {
DEBUG_MSG(DLVL_DEVEL, "Skipping %s, reason %s", entry->d_name, strerror(errno));
continue;
}
///Convert stat to string
Entries[std::string(entry->d_name)] = StatBuf;
}
}
}
void Filesystem::Directory::Print() {
/// \todo Remove? Libraries shouldn't print stuff.
if (!ValidDir) {
DEBUG_MSG(DLVL_ERROR, "%s is not a valid directory", (MyBase + MyPath).c_str());
return;
}
printf("%s:\n", (MyBase + MyPath).c_str());
for (std::map<std::string, struct stat>::iterator it = Entries.begin(); it != Entries.end(); it++) {
printf("\t%s\n", (*it).first.c_str());
}
printf("\n");
}
bool Filesystem::Directory::IsDir() {
return ValidDir;
}
std::string Filesystem::Directory::PWD() {
return "/" + MyPath;
}
std::string Filesystem::Directory::LIST(std::vector<std::string> ActiveStreams) {
FillEntries();
int MyPermissions;
std::stringstream Converter;
passwd * pwd; //For Username
group * grp; //For Groupname
tm * tm; //For time localisation
char datestring[256]; //For time localisation
std::string MyLoc = MyBase + MyPath;
if (MyLoc[MyLoc.size() - 1] != '/') {
MyLoc += "/";
}
for (std::map<std::string, struct stat>::iterator it = Entries.begin(); it != Entries.end(); it++) {
bool Active = (std::find(ActiveStreams.begin(), ActiveStreams.end(), (*it).first) != ActiveStreams.end());
if ((Active && (MyVisible[MyPath] & S_ACTIVE)) || ((!Active) && (MyVisible[MyPath] & S_INACTIVE)) || (((*it).second.st_mode / 010000) == 4)) {
if (((*it).second.st_mode / 010000) == 4) {
Converter << 'd';
} else {
Converter << '-';
}
MyPermissions = (((*it).second.st_mode % 010000) / 0100);
if (MyPermissions & 4) {
Converter << 'r';
} else {
Converter << '-';
}
if (MyPermissions & 2) {
Converter << 'w';
} else {
Converter << '-';
}
if (MyPermissions & 1) {
Converter << 'x';
} else {
Converter << '-';
}
MyPermissions = (((*it).second.st_mode % 0100) / 010);
if (MyPermissions & 4) {
Converter << 'r';
} else {
Converter << '-';
}
if (MyPermissions & 2) {
Converter << 'w';
} else {
Converter << '-';
}
if (MyPermissions & 1) {
Converter << 'x';
} else {
Converter << '-';
}
MyPermissions = ((*it).second.st_mode % 010);
if (MyPermissions & 4) {
Converter << 'r';
} else {
Converter << '-';
}
if (MyPermissions & 2) {
Converter << 'w';
} else {
Converter << '-';
}
if (MyPermissions & 1) {
Converter << 'x';
} else {
Converter << '-';
}
Converter << ' ';
Converter << (*it).second.st_nlink;
Converter << ' ';
if ((pwd = getpwuid((*it).second.st_uid))) {
Converter << pwd->pw_name;
} else {
Converter << (*it).second.st_uid;
}
Converter << ' ';
if ((grp = getgrgid((*it).second.st_gid))) {
Converter << grp->gr_name;
} else {
Converter << (*it).second.st_gid;
}
Converter << ' ';
Converter << (*it).second.st_size;
Converter << ' ';
tm = localtime(&((*it).second.st_mtime));
strftime(datestring, sizeof(datestring), "%b %d %H:%M", tm);
Converter << datestring;
Converter << ' ';
Converter << (*it).first;
Converter << '\n';
}
}
return Converter.str();
}
bool Filesystem::Directory::CWD(std::string Path) {
if (Path[0] == '/') {
Path.erase(0, 1);
MyPath = Path;
} else {
if (MyPath != "") {
MyPath += "/";
}
MyPath += Path;
}
FillEntries();
printf("New Path: %s\n", MyPath.c_str());
if (MyPermissions.find(MyPath) != MyPermissions.end()) {
printf("\tPermissions: %d\n", MyPermissions[MyPath]);
}
return SimplifyPath();
}
bool Filesystem::Directory::CDUP() {
return CWD("..");
}
std::string Filesystem::Directory::RETR(std::string Path) {
std::string Result;
std::string FileName;
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
} else {
FileName = MyBase + MyPath + "/" + Path;
}
std::ifstream File;
File.open(FileName.c_str());
while (File.good()) {
Result += File.get();
}
File.close();
return Result;
}
void Filesystem::Directory::STOR(std::string Path, std::string Data) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_STOR)) {
std::string FileName;
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
} else {
FileName = MyBase + MyPath + "/" + Path;
}
std::ofstream File;
File.open(FileName.c_str());
File << Data;
File.close();
}
}
bool Filesystem::Directory::SimplifyPath() {
MyPath += "/";
std::vector<std::string> TempPath;
std::string TempString;
for (std::string::iterator it = MyPath.begin(); it != MyPath.end(); it++) {
if ((*it) == '/') {
if (TempString == "..") {
if (!TempPath.size()) {
return false;
}
TempPath.erase((TempPath.end() - 1));
} else if (TempString != "." && TempString != "") {
TempPath.push_back(TempString);
}
TempString = "";
} else {
TempString += (*it);
}
}
MyPath = "";
for (std::vector<std::string>::iterator it = TempPath.begin(); it != TempPath.end(); it++) {
MyPath += (*it);
if (it != (TempPath.end() - 1)) {
MyPath += "/";
}
}
if (MyVisible.find(MyPath) == MyVisible.end()) {
MyVisible[MyPath] = S_ALL;
}
return true;
}
bool Filesystem::Directory::DELE(std::string Path) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_DELE)) {
std::string FileName;
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
} else {
FileName = MyBase + MyPath + "/" + Path;
}
if (std::remove(FileName.c_str())) {
DEBUG_MSG(DLVL_ERROR, "Removing file %s failed", FileName.c_str());
return false;
}
return true;
}
return false;
}
bool Filesystem::Directory::MKD(std::string Path) {
std::string FileName;
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
} else {
FileName = MyBase + MyPath + "/" + Path;
}
if (mkdir(FileName.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
DEBUG_MSG(DLVL_ERROR, "Creating directory %s failed", FileName.c_str());
return false;
}
MyVisible[FileName] = S_ALL;
return true;
}
bool Filesystem::Directory::Rename(std::string From, std::string To) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_RNFT)) {
std::string FileFrom;
if (From[0] == '/') {
From.erase(0, 1);
FileFrom = MyBase + From;
} else {
FileFrom = MyBase + MyPath + "/" + From;
}
std::string FileTo;
if (To[0] == '/') {
FileTo = MyBase + To;
} else {
FileTo = MyBase + MyPath + "/" + To;
}
if (std::rename(FileFrom.c_str(), FileTo.c_str())) {
DEBUG_MSG(DLVL_ERROR, "Renaming %s to %s failed", FileFrom.c_str(), FileTo.c_str());
return false;
}
return true;
}
return false;
}
void Filesystem::Directory::SetPermissions(std::string Path, char Permissions) {
MyPermissions[Path] = Permissions;
}
bool Filesystem::Directory::HasPermission(char Permission) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & Permission)) {
return true;
}
return false;
}
void Filesystem::Directory::SetVisibility(std::string Pathname, char Visible) {
MyVisible[Pathname] = Visible;
}

View file

@ -1,67 +0,0 @@
#pragma once
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <map>
#include <sstream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <locale.h>
#include <langinfo.h>
#include <stdint.h>
#include <errno.h>
namespace Filesystem {
enum DIR_Permissions {
P_LIST = 0x01, //List
P_RETR = 0x02, //Retrieve
P_STOR = 0x04, //Store
P_RNFT = 0x08, //Rename From/To
P_DELE = 0x10, //Delete
P_MKD = 0x20, //Make directory
P_RMD = 0x40, //Remove directory
};
enum DIR_Show {
S_NONE = 0x00, S_ACTIVE = 0x01, S_INACTIVE = 0x02, S_ALL = 0x03,
};
class Directory {
public:
Directory(std::string PathName = "", std::string BasePath = ".");
~Directory();
void Print();
bool IsDir();
std::string PWD();
std::string LIST(std::vector<std::string> ActiveStreams = std::vector<std::string>());
bool CWD(std::string Path);
bool CDUP();
bool DELE(std::string Path);
bool MKD(std::string Path);
std::string RETR(std::string Path);
void STOR(std::string Path, std::string Data);
bool Rename(std::string From, std::string To);
void SetPermissions(std::string PathName, char Permissions);
bool HasPermission(char Permission);
void SetVisibility(std::string Pathname, char Visible);
private:
bool ValidDir;
bool SimplifyPath();
void FillEntries();
std::string MyBase;
std::string MyPath;
std::map<std::string, struct stat> Entries;
std::map<std::string, char> MyPermissions;
std::map<std::string, char> MyVisible;
};
//Directory Class
}//Filesystem namespace

View file

@ -1,557 +0,0 @@
#include "ftp.h"
FTP::User::User(Socket::Connection NewConnection, std::map<std::string, std::string> Credentials) {
Conn = NewConnection;
MyPassivePort = 0;
USER = "";
PASS = "";
MODE = MODE_STREAM;
STRU = STRU_FILE;
TYPE = TYPE_ASCII_NONPRINT;
PORT = 20;
RNFR = "";
AllCredentials = Credentials;
MyDir = Filesystem::Directory("", FTPBasePath);
MyDir.SetPermissions("", Filesystem::P_LIST);
MyDir.SetPermissions("Unconverted", Filesystem::P_LIST | Filesystem::P_DELE | Filesystem::P_RNFT | Filesystem::P_STOR | Filesystem::P_RETR);
MyDir.SetPermissions("Converted", Filesystem::P_LIST | Filesystem::P_DELE | Filesystem::P_RNFT | Filesystem::P_RETR);
MyDir.SetPermissions("OnDemand", Filesystem::P_LIST | Filesystem::P_RETR);
MyDir.SetPermissions("Live", Filesystem::P_LIST);
MyDir.SetVisibility("Converted", Filesystem::S_INACTIVE);
MyDir.SetVisibility("OnDemand", Filesystem::S_ACTIVE);
}
FTP::User::~User() {
}
int FTP::User::ParseCommand(std::string Command) {
Commands ThisCmd = CMD_NOCMD;
if (Command.substr(0, 4) == "NOOP") {
ThisCmd = CMD_NOOP;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "USER") {
ThisCmd = CMD_USER;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "PASS") {
ThisCmd = CMD_PASS;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "QUIT") {
ThisCmd = CMD_QUIT;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "PORT") {
ThisCmd = CMD_PORT;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "RETR") {
ThisCmd = CMD_RETR;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "STOR") {
ThisCmd = CMD_STOR;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "TYPE") {
ThisCmd = CMD_TYPE;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "MODE") {
ThisCmd = CMD_MODE;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "STRU") {
ThisCmd = CMD_STRU;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "EPSV") {
ThisCmd = CMD_EPSV;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "PASV") {
ThisCmd = CMD_PASV;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "LIST") {
ThisCmd = CMD_LIST;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "CDUP") {
ThisCmd = CMD_CDUP;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "DELE") {
ThisCmd = CMD_DELE;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "RNFR") {
ThisCmd = CMD_RNFR;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "RNTO") {
ThisCmd = CMD_RNTO;
Command.erase(0, 5);
}
if (Command.substr(0, 3) == "PWD") {
ThisCmd = CMD_PWD;
Command.erase(0, 4);
}
if (Command.substr(0, 3) == "CWD") {
ThisCmd = CMD_CWD;
Command.erase(0, 4);
}
if (Command.substr(0, 3) == "RMD") {
ThisCmd = CMD_RMD;
Command.erase(0, 4);
}
if (Command.substr(0, 3) == "MKD") {
ThisCmd = CMD_MKD;
Command.erase(0, 4);
}
if (ThisCmd != CMD_RNTO) {
RNFR = "";
}
switch (ThisCmd) {
case CMD_NOOP: {
return 200; //Command okay.
break;
}
case CMD_USER: {
USER = "";
PASS = "";
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
USER = Command;
return 331; //User name okay, need password.
break;
}
case CMD_PASS: {
if (USER == "") {
return 503;
} //Bad sequence of commands
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
PASS = Command;
if (!LoggedIn()) {
USER = "";
PASS = "";
return 530; //Not logged in.
}
return 230;
break;
}
case CMD_LIST: {
Socket::Connection Connected = Passive.accept();
if (Connected.connected()) {
Conn.SendNow("125 Data connection already open; transfer starting.\n");
} else {
Conn.SendNow("150 File status okay; about to open data connection.\n");
}
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string tmpstr = MyDir.LIST(ActiveStreams);
Connected.SendNow(tmpstr);
Connected.close();
return 226;
break;
}
case CMD_QUIT: {
return 221; //Service closing control connection. Logged out if appropriate.
break;
}
case CMD_PORT: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
PORT = atoi(Command.c_str());
return 200; //Command okay.
break;
}
case CMD_EPSV: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
MyPassivePort = (rand() % 9999);
Passive = Socket::Server(MyPassivePort, "0.0.0.0", true);
return 229;
break;
}
case CMD_PASV: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
MyPassivePort = (rand() % 9999) + 49152;
Passive = Socket::Server(MyPassivePort, "0.0.0.0", true);
return 227;
break;
}
case CMD_RETR: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (!MyDir.HasPermission(Filesystem::P_RETR)) {
return 550;
} //Access denied.
Socket::Connection Connected = Passive.accept();
if (Connected.connected()) {
Conn.SendNow("125 Data connection already open; transfer starting.\n");
} else {
Conn.SendNow("150 File status okay; about to open data connection.\n");
}
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string tmpstr = MyDir.RETR(Command);
Connected.SendNow(tmpstr);
Connected.close();
return 226;
break;
}
case CMD_STOR: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (!MyDir.HasPermission(Filesystem::P_STOR)) {
return 550;
} //Access denied.
Socket::Connection Connected = Passive.accept();
if (Connected.connected()) {
Conn.SendNow("125 Data connection already open; transfer starting.\n");
} else {
Conn.SendNow("150 File status okay; about to open data connection.\n");
}
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string Buffer;
while (Connected.spool()) {
}
/// \todo Comment me back in. ^_^
//Buffer = Connected.Received();
MyDir.STOR(Command, Buffer);
return 250;
break;
}
case CMD_TYPE: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (Command.size() != 1 && Command.size() != 3) {
return 501;
} //Syntax error in parameters or arguments.
switch (Command[0]) {
case 'A': {
if (Command.size() > 1) {
if (Command[1] != ' ') {
return 501;
} //Syntax error in parameters or arguments.
if (Command[2] != 'N') {
return 504;
} //Command not implemented for that parameter.
}
TYPE = TYPE_ASCII_NONPRINT;
break;
}
case 'I': {
if (Command.size() > 1) {
if (Command[1] != ' ') {
return 501;
} //Syntax error in parameters or arguments.
if (Command[2] != 'N') {
return 504;
} //Command not implemented for that parameter.
}
TYPE = TYPE_IMAGE_NONPRINT;
break;
}
default: {
return 504; //Command not implemented for that parameter.
break;
}
}
return 200; //Command okay.
break;
}
case CMD_MODE: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (Command.size() != 1) {
return 501;
} //Syntax error in parameters or arguments.
if (Command[0] != 'S') {
return 504;
} //Command not implemented for that parameter.
MODE = MODE_STREAM;
return 200; //Command okay.
break;
}
case CMD_STRU: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (Command.size() != 1) {
return 501;
} //Syntax error in parameters or arguments.
switch (Command[0]) {
case 'F': {
STRU = STRU_FILE;
break;
}
case 'R': {
STRU = STRU_RECORD;
break;
}
default: {
return 504; //Command not implemented for that parameter.
break;
}
}
return 200; //Command okay.
break;
}
case CMD_PWD: {
if (!LoggedIn()) {
return 550;
} //Not logged in.
if (Command != "") {
return 501;
} //Syntax error in parameters or arguments.
return 2570; //257 -- 0 to indicate PWD over MKD
break;
}
case CMD_CWD: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
Filesystem::Directory TmpDir = MyDir;
if (TmpDir.CWD(Command)) {
if (TmpDir.IsDir()) {
MyDir = TmpDir;
return 250;
}
}
return 550;
break;
}
case CMD_CDUP: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command != "") {
return 501;
} //Syntax error in parameters or arguments.
Filesystem::Directory TmpDir = MyDir;
if (TmpDir.CDUP()) {
if (TmpDir.IsDir()) {
MyDir = TmpDir;
return 250;
}
}
return 550;
break;
}
case CMD_DELE: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (!MyDir.DELE(Command)) {
return 550;
}
return 250;
break;
}
case CMD_RMD: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (!MyDir.HasPermission(Filesystem::P_RMD)) {
return 550;
}
if (!MyDir.DELE(Command)) {
return 550;
}
return 250;
break;
}
case CMD_MKD: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (!MyDir.HasPermission(Filesystem::P_MKD)) {
return 550;
}
if (!MyDir.MKD(Command)) {
return 550;
}
return 2571;
break;
}
case CMD_RNFR: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
RNFR = Command;
return 350; //Awaiting further information
}
case CMD_RNTO: {
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (RNFR == "") {
return 503;
} //Bad sequence of commands
if (!MyDir.Rename(RNFR, Command)) {
return 550;
}
return 250;
}
default: {
return 502; //Command not implemented.
break;
}
}
}
bool FTP::User::LoggedIn() {
if (USER == "" || PASS == "") {
return false;
}
if (!AllCredentials.size()) {
return true;
}
if ((AllCredentials.find(USER) != AllCredentials.end()) && AllCredentials[USER] == PASS) {
return true;
}
return false;
}
std::string FTP::User::NumToMsg(int MsgNum) {
std::string Result;
switch (MsgNum) {
case 200: {
Result = "200 Message okay.\n";
break;
}
case 221: {
Result = "221 Service closing control connection. Logged out if appropriate.\n";
break;
}
case 226: {
Result = "226 Closing data connection.\n";
break;
}
case 227: {
std::stringstream sstr;
sstr << "227 Entering passive mode (0,0,0,0,";
sstr << (MyPassivePort >> 8) % 256;
sstr << ",";
sstr << MyPassivePort % 256;
sstr << ").\n";
Result = sstr.str();
break;
}
case 229: {
std::stringstream sstr;
sstr << "229 Entering extended passive mode (|||";
sstr << MyPassivePort;
sstr << "|).\n";
Result = sstr.str();
break;
}
case 230: {
Result = "230 User logged in, proceed.\n";
break;
}
case 250: {
Result = "250 Requested file action okay, completed.\n";
break;
}
case 2570: { //PWD
Result = "257 \"" + MyDir.PWD() + "\" selected as PWD\n";
break;
}
case 2571: { //MKD
Result = "257 \"" + MyDir.PWD() + "\" created\n";
break;
}
case 331: {
Result = "331 User name okay, need password.\n";
break;
}
case 350: {
Result = "350 Requested file action pending further information\n";
break;
}
case 501: {
Result = "501 Syntax error in parameters or arguments.\n";
break;
}
case 502: {
Result = "502 Command not implemented.\n";
break;
}
case 503: {
Result = "503 Bad sequence of commands.\n";
break;
}
case 504: {
Result = "504 Command not implemented for that parameter.\n";
break;
}
case 530: {
Result = "530 Not logged in.\n";
break;
}
case 550: {
Result = "550 Requested action not taken.\n";
break;
}
default: {
Result = "Error msg not implemented?\n";
break;
}
}
return Result;
}

View file

@ -1,82 +0,0 @@
#include <map>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <sstream>
#include <string>
#include "./socket.h"
#include "./filesystem.h"
#include <unistd.h>
#include "./json.h"
namespace FTP {
static std::string FTPBasePath = "/tmp/mist/OnDemand/";
enum Mode {
MODE_STREAM,
};
//FTP::Mode enumeration
enum Structure {
STRU_FILE, STRU_RECORD,
};
//FTP::Structure enumeration
enum Type {
TYPE_ASCII_NONPRINT, TYPE_IMAGE_NONPRINT,
};
//FTP::Type enumeration
enum Commands {
CMD_NOCMD,
CMD_NOOP,
CMD_USER,
CMD_PASS,
CMD_QUIT,
CMD_PORT,
CMD_RETR,
CMD_STOR,
CMD_TYPE,
CMD_MODE,
CMD_STRU,
CMD_EPSV,
CMD_PASV,
CMD_LIST,
CMD_PWD,
CMD_CWD,
CMD_CDUP,
CMD_DELE,
CMD_RMD,
CMD_MKD,
CMD_RNFR,
CMD_RNTO,
};
//FTP::Commands enumeration
class User {
public:
User(Socket::Connection NewConnection, std::map<std::string, std::string> Credentials);
~User();
int ParseCommand(std::string Command);
bool LoggedIn();
std::string NumToMsg(int MsgNum);
Socket::Connection Conn;
private:
std::map<std::string, std::string> AllCredentials;
std::string USER;
std::string PASS;
Mode MODE;
Structure STRU;
Type TYPE;
int PORT;
Socket::Server Passive;
int MyPassivePort;
Filesystem::Directory MyDir;
std::string RNFR;
std::vector<std::string> ActiveStreams;
};
//FTP::User class
}//FTP Namespace