annotate data/fileio/PlaylistFileReader.cpp @ 683:f84f147572b9

Avoid crash when generating/processing a very short file
author Chris Cannam
date Wed, 11 May 2011 11:04:02 +0100
parents 5746c559af15
children b4a8d8221eaf
rev   line source
Chris@297 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@297 2
Chris@297 3 /*
Chris@297 4 Sonic Visualiser
Chris@297 5 An audio file viewer and annotation editor.
Chris@297 6 Centre for Digital Music, Queen Mary, University of London.
Chris@297 7 This file copyright 2007 QMUL.
Chris@297 8
Chris@297 9 This program is free software; you can redistribute it and/or
Chris@297 10 modify it under the terms of the GNU General Public License as
Chris@297 11 published by the Free Software Foundation; either version 2 of the
Chris@297 12 License, or (at your option) any later version. See the file
Chris@297 13 COPYING included with this distribution for more information.
Chris@297 14 */
Chris@297 15
Chris@297 16 #include "PlaylistFileReader.h"
Chris@297 17
Chris@297 18 #include <QFile>
Chris@297 19 #include <QTextStream>
Chris@297 20 #include <QStringList>
Chris@440 21 #include <QFileInfo>
Chris@440 22 #include <QDir>
Chris@440 23
Chris@440 24 #include <iostream>
Chris@297 25
Chris@401 26 PlaylistFileReader::PlaylistFileReader(QString path) :
Chris@401 27 m_source(path),
Chris@401 28 m_file(0)
Chris@297 29 {
Chris@401 30 if (!m_source.isAvailable()) {
Chris@401 31 m_error = QFile::tr("File or URL \"%1\" could not be retrieved")
Chris@401 32 .arg(path);
Chris@401 33 return;
Chris@401 34 }
Chris@401 35 init();
Chris@401 36 }
Chris@401 37
Chris@401 38 PlaylistFileReader::PlaylistFileReader(FileSource source) :
Chris@401 39 m_source(source),
Chris@401 40 m_file(0)
Chris@401 41 {
Chris@401 42 if (!m_source.isAvailable()) {
Chris@401 43 m_error = QFile::tr("File or URL \"%1\" could not be retrieved")
Chris@401 44 .arg(source.getLocation());
Chris@401 45 return;
Chris@401 46 }
Chris@401 47 init();
Chris@401 48 }
Chris@401 49
Chris@401 50 PlaylistFileReader::~PlaylistFileReader()
Chris@401 51 {
Chris@401 52 if (m_file) m_file->close();
Chris@401 53 delete m_file;
Chris@401 54 }
Chris@401 55
Chris@401 56 void
Chris@401 57 PlaylistFileReader::init()
Chris@401 58 {
Chris@401 59 if (!m_source.isAvailable()) return;
Chris@401 60
Chris@401 61 m_source.waitForData();
Chris@401 62
Chris@440 63 QString filename = m_source.getLocalFilename();
Chris@440 64
Chris@440 65 m_file = new QFile(filename);
Chris@297 66 bool good = false;
Chris@297 67
Chris@297 68 if (!m_file->exists()) {
Chris@401 69 m_error = QFile::tr("File \"%1\" does not exist")
Chris@401 70 .arg(m_source.getLocation());
Chris@297 71 } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
Chris@401 72 m_error = QFile::tr("Failed to open file \"%1\"")
Chris@401 73 .arg(m_source.getLocation());
Chris@297 74 } else {
Chris@297 75 good = true;
Chris@297 76 }
Chris@297 77
Chris@440 78 if (good) {
Chris@440 79 if (!m_source.isRemote()) {
Chris@440 80 m_basedir = QFileInfo(filename).dir().canonicalPath();
Chris@440 81 }
Chris@440 82 }
Chris@440 83
Chris@297 84 if (!good) {
Chris@297 85 delete m_file;
Chris@297 86 m_file = 0;
Chris@297 87 }
Chris@297 88 }
Chris@297 89
Chris@297 90 bool
Chris@297 91 PlaylistFileReader::isOK() const
Chris@297 92 {
Chris@297 93 return (m_file != 0);
Chris@297 94 }
Chris@297 95
Chris@297 96 QString
Chris@297 97 PlaylistFileReader::getError() const
Chris@297 98 {
Chris@297 99 return m_error;
Chris@297 100 }
Chris@297 101
Chris@297 102 PlaylistFileReader::Playlist
Chris@297 103 PlaylistFileReader::load() const
Chris@297 104 {
Chris@297 105 if (!m_file) return Playlist();
Chris@297 106
Chris@297 107 QTextStream in(m_file);
Chris@297 108 in.seek(0);
Chris@297 109
Chris@297 110 Playlist playlist;
Chris@297 111
Chris@297 112 while (!in.atEnd()) {
Chris@297 113
Chris@297 114 // cope with old-style Mac line endings (c.f. CSVFileReader)
Chris@297 115 // as well as DOS/Unix style
Chris@297 116
Chris@297 117 QString chunk = in.readLine();
Chris@297 118 QStringList lines = chunk.split('\r', QString::SkipEmptyParts);
Chris@297 119
Chris@440 120 for (int li = 0; li < lines.size(); ++li) {
Chris@297 121
Chris@297 122 QString line = lines[li];
Chris@297 123
Chris@297 124 if (line.startsWith("#")) continue;
Chris@297 125
Chris@440 126 // line is expected to be a URL or a file path. If it
Chris@440 127 // appears to be a local relative file path, then we
Chris@440 128 // should check whether it can be resolved relative to the
Chris@440 129 // location of the playlist file and, if so, do so.
Chris@440 130
Chris@440 131 if (!FileSource::isRemote(line)) {
Chris@440 132 if (QFileInfo(line).isRelative() && m_basedir != "") {
Chris@440 133 QString testpath = QDir(m_basedir).filePath(line);
Chris@440 134 if (QFileInfo(testpath).exists() &&
Chris@440 135 QFileInfo(testpath).isFile()) {
Chris@440 136 std::cerr << "Path \"" << line.toStdString()
Chris@440 137 << "\" is relative, resolving to \""
Chris@440 138 << testpath.toStdString() << "\""
Chris@440 139 << std::endl;
Chris@440 140 line = testpath;
Chris@440 141 }
Chris@440 142 }
Chris@440 143 }
Chris@440 144
Chris@297 145 playlist.push_back(line);
Chris@297 146 }
Chris@297 147 }
Chris@297 148
Chris@297 149 return playlist;
Chris@297 150 }
Chris@297 151
Chris@297 152 void
Chris@297 153 PlaylistFileReader::getSupportedExtensions(std::set<QString> &extensions)
Chris@297 154 {
Chris@297 155 extensions.insert("m3u");
Chris@297 156 }