LocateUri: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann 2016-10-27 21:59:17 +02:00
parent 726fc53e62
commit 6961bd61ca
16 changed files with 74 additions and 132 deletions

View File

@ -24,25 +24,19 @@
#include "ls.hxx" #include "ls.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/StringCompare.hxx" #include "util/StringCompare.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
#include "storage/StorageInterface.hxx" #include "storage/StorageInterface.hxx"
#endif #endif
const Domain locate_uri_domain("locate_uri");
static LocatedUri static LocatedUri
LocateFileUri(const char *uri, const Client *client, LocateFileUri(const char *uri, const Client *client
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const Storage *storage, , const Storage *storage
#endif #endif
Error &error) )
{ {
auto path = AllocatedPath::FromUTF8(uri, error); auto path = AllocatedPath::FromUTF8Throw(uri);
if (path.IsNull())
return LocatedUri::Unknown();
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
if (storage != nullptr) { if (storage != nullptr) {
@ -54,23 +48,21 @@ LocateFileUri(const char *uri, const Client *client,
} }
#endif #endif
if (client != nullptr && !client->AllowFile(path, error)) if (client != nullptr)
return LocatedUri::Unknown(); client->AllowFile(path);
return LocatedUri(LocatedUri::Type::PATH, uri, std::move(path)); return LocatedUri(LocatedUri::Type::PATH, uri, std::move(path));
} }
static LocatedUri static LocatedUri
LocateAbsoluteUri(const char *uri, LocateAbsoluteUri(const char *uri
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const Storage *storage, , const Storage *storage
#endif #endif
Error &error) )
{ {
if (!uri_supported_scheme(uri)) { if (!uri_supported_scheme(uri))
error.Set(locate_uri_domain, "Unsupported URI scheme"); throw std::runtime_error("Unsupported URI scheme");
return LocatedUri::Unknown();
}
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
if (storage != nullptr) { if (storage != nullptr) {
@ -84,37 +76,35 @@ LocateAbsoluteUri(const char *uri,
} }
LocatedUri LocatedUri
LocateUri(const char *uri, const Client *client, LocateUri(const char *uri, const Client *client
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const Storage *storage, , const Storage *storage
#endif #endif
Error &error) )
{ {
/* skip the obsolete "file://" prefix */ /* skip the obsolete "file://" prefix */
const char *path_utf8 = StringAfterPrefix(uri, "file://"); const char *path_utf8 = StringAfterPrefix(uri, "file://");
if (path_utf8 != nullptr) { if (path_utf8 != nullptr) {
if (!PathTraitsUTF8::IsAbsolute(path_utf8)) { if (!PathTraitsUTF8::IsAbsolute(path_utf8))
error.Set(locate_uri_domain, "Malformed file:// URI"); throw std::runtime_error("Malformed file:// URI");
return LocatedUri::Unknown();
}
return LocateFileUri(path_utf8, client, return LocateFileUri(path_utf8, client
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
storage, , storage
#endif #endif
error); );
} else if (PathTraitsUTF8::IsAbsolute(uri)) } else if (PathTraitsUTF8::IsAbsolute(uri))
return LocateFileUri(uri, client, return LocateFileUri(uri, client
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
storage, , storage
#endif #endif
error); );
else if (uri_has_scheme(uri)) else if (uri_has_scheme(uri))
return LocateAbsoluteUri(uri, return LocateAbsoluteUri(uri
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
storage, , storage
#endif #endif
error); );
else else
return LocatedUri(LocatedUri::Type::RELATIVE, uri); return LocatedUri(LocatedUri::Type::RELATIVE, uri);
} }

View File

@ -35,8 +35,6 @@
#endif #endif
#endif #endif
class Domain;
class Error;
class Client; class Client;
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
@ -45,11 +43,6 @@ class Storage;
struct LocatedUri { struct LocatedUri {
enum class Type { enum class Type {
/**
* Failed to parse the URI.
*/
UNKNOWN,
/** /**
* An absolute URI with a supported scheme. * An absolute URI with a supported scheme.
*/ */
@ -76,22 +69,13 @@ struct LocatedUri {
LocatedUri(Type _type, const char *_uri, LocatedUri(Type _type, const char *_uri,
AllocatedPath &&_path=AllocatedPath::Null()) AllocatedPath &&_path=AllocatedPath::Null())
:type(_type), canonical_uri(_uri), path(std::move(_path)) {} :type(_type), canonical_uri(_uri), path(std::move(_path)) {}
gcc_const
static LocatedUri Unknown() {
return LocatedUri(Type::UNKNOWN, nullptr);
}
bool IsUnknown() const {
return type == Type::UNKNOWN;
}
}; };
extern const Domain locate_uri_domain;
/** /**
* Classify a URI. * Classify a URI.
* *
* Throws #std::runtime_error on error.
*
* @param client the #Client that is used to determine whether a local * @param client the #Client that is used to determine whether a local
* file is allowed; nullptr disables the check and allows all local * file is allowed; nullptr disables the check and allows all local
* files * files
@ -100,10 +84,10 @@ extern const Domain locate_uri_domain;
* that feature is disabled if this parameter is nullptr * that feature is disabled if this parameter is nullptr
*/ */
LocatedUri LocatedUri
LocateUri(const char *uri, const Client *client, LocateUri(const char *uri, const Client *client
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const Storage *storage, , const Storage *storage
#endif #endif
Error &error); );
#endif #endif

View File

@ -68,9 +68,8 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
} }
unsigned AppendURI(const SongLoader &loader, unsigned AppendURI(const SongLoader &loader,
const char *uri_utf8, const char *uri_utf8) {
Error &error) { return playlist.AppendURI(pc, loader, uri_utf8);
return playlist.AppendURI(pc, loader, uri_utf8, error);
} }
void DeletePosition(unsigned position) { void DeletePosition(unsigned position) {

View File

@ -373,17 +373,12 @@ try {
throw; throw;
} }
bool void
spl_append_uri(const char *utf8file, spl_append_uri(const char *utf8file,
const SongLoader &loader, const char *url, const SongLoader &loader, const char *url)
Error &error)
{ {
std::unique_ptr<DetachedSong> song(loader.LoadSong(url, error)); std::unique_ptr<DetachedSong> song(loader.LoadSong(url));
if (song == nullptr)
return false;
spl_append_song(utf8file, *song); spl_append_song(utf8file, *song);
return true;
} }
static void static void

View File

@ -73,10 +73,12 @@ spl_remove_index(const char *utf8path, unsigned pos);
void void
spl_append_song(const char *utf8path, const DetachedSong &song); spl_append_song(const char *utf8path, const DetachedSong &song);
bool /**
* Throws #std::runtime_error on error.
*/
void
spl_append_uri(const char *path_utf8, spl_append_uri(const char *path_utf8,
const SongLoader &loader, const char *uri_utf8, const SongLoader &loader, const char *uri_utf8);
Error &error);
void void
spl_rename(const char *utf8from, const char *utf8to); spl_rename(const char *utf8from, const char *utf8to);

View File

@ -74,9 +74,6 @@ DetachedSong *
SongLoader::LoadSong(const LocatedUri &located_uri) const SongLoader::LoadSong(const LocatedUri &located_uri) const
{ {
switch (located_uri.type) { switch (located_uri.type) {
case LocatedUri::Type::UNKNOWN:
gcc_unreachable();
case LocatedUri::Type::ABSOLUTE: case LocatedUri::Type::ABSOLUTE:
return new DetachedSong(located_uri.canonical_uri); return new DetachedSong(located_uri.canonical_uri);
@ -91,20 +88,17 @@ SongLoader::LoadSong(const LocatedUri &located_uri) const
} }
DetachedSong * DetachedSong *
SongLoader::LoadSong(const char *uri_utf8, Error &error) const SongLoader::LoadSong(const char *uri_utf8) const
{ {
#if !CLANG_CHECK_VERSION(3,6) #if !CLANG_CHECK_VERSION(3,6)
/* disabled on clang due to -Wtautological-pointer-compare */ /* disabled on clang due to -Wtautological-pointer-compare */
assert(uri_utf8 != nullptr); assert(uri_utf8 != nullptr);
#endif #endif
const auto located_uri = LocateUri(uri_utf8, client, const auto located_uri = LocateUri(uri_utf8, client
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
storage, , storage
#endif #endif
error); );
if (located_uri.IsUnknown())
return nullptr;
return LoadSong(located_uri); return LoadSong(located_uri);
} }

View File

@ -70,8 +70,11 @@ public:
DetachedSong *LoadSong(const LocatedUri &uri) const; DetachedSong *LoadSong(const LocatedUri &uri) const;
/**
* Throws #std::runtime_error on error.
*/
gcc_nonnull_all gcc_nonnull_all
DetachedSong *LoadSong(const char *uri_utf8, Error &error) const; DetachedSong *LoadSong(const char *uri_utf8) const;
private: private:
gcc_nonnull_all gcc_nonnull_all

View File

@ -21,7 +21,6 @@
#include "CommandError.hxx" #include "CommandError.hxx"
#include "PlaylistError.hxx" #include "PlaylistError.hxx"
#include "db/DatabaseError.hxx" #include "db/DatabaseError.hxx"
#include "LocateUri.hxx"
#include "client/Response.hxx" #include "client/Response.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "Log.hxx" #include "Log.hxx"
@ -89,8 +88,6 @@ ToAck(const Error &error)
{ {
if (error.IsDomain(ack_domain)) { if (error.IsDomain(ack_domain)) {
return (enum ack)error.GetCode(); return (enum ack)error.GetCode();
} else if (error.IsDomain(locate_uri_domain)) {
return ACK_ERROR_ARG;
} else if (error.IsDomain(errno_domain)) { } else if (error.IsDomain(errno_domain)) {
return ACK_ERROR_SYSTEM; return ACK_ERROR_SYSTEM;
} }

View File

@ -216,16 +216,12 @@ handle_read_comments(Client &client, Request args, Response &r)
const char *const uri = args.front(); const char *const uri = args.front();
Error error; const auto located_uri = LocateUri(uri, &client
const auto located_uri = LocateUri(uri, &client,
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
nullptr, , nullptr
#endif #endif
error); );
switch (located_uri.type) { switch (located_uri.type) {
case LocatedUri::Type::UNKNOWN:
return print_error(r, error);
case LocatedUri::Type::ABSOLUTE: case LocatedUri::Type::ABSOLUTE:
return read_stream_comments(r, located_uri.canonical_uri); return read_stream_comments(r, located_uri.canonical_uri);

View File

@ -123,17 +123,13 @@ handle_listfiles(Client &client, Request args, Response &r)
/* default is root directory */ /* default is root directory */
const auto uri = args.GetOptional(0, ""); const auto uri = args.GetOptional(0, "");
Error error; const auto located_uri = LocateUri(uri, &client
const auto located_uri = LocateUri(uri, &client,
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
nullptr, , nullptr
#endif #endif
error); );
switch (located_uri.type) { switch (located_uri.type) {
case LocatedUri::Type::UNKNOWN:
return print_error(r, error);
case LocatedUri::Type::ABSOLUTE: case LocatedUri::Type::ABSOLUTE:
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
/* use storage plugin to list remote directory */ /* use storage plugin to list remote directory */
@ -238,17 +234,13 @@ handle_lsinfo(Client &client, Request args, Response &r)
compatibility, work around this here */ compatibility, work around this here */
uri = ""; uri = "";
Error error; const auto located_uri = LocateUri(uri, &client
const auto located_uri = LocateUri(uri, &client,
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
nullptr, , nullptr
#endif #endif
error); );
switch (located_uri.type) { switch (located_uri.type) {
case LocatedUri::Type::UNKNOWN:
return print_error(r, error);
case LocatedUri::Type::ABSOLUTE: case LocatedUri::Type::ABSOLUTE:
return handle_lsinfo_absolute(r, located_uri.canonical_uri); return handle_lsinfo_absolute(r, located_uri.canonical_uri);

View File

@ -165,7 +165,8 @@ handle_playlistadd(Client &client, Request args, Response &r)
Error error; Error error;
if (uri_has_scheme(uri)) { if (uri_has_scheme(uri)) {
const SongLoader loader(client); const SongLoader loader(client);
success = spl_append_uri(playlist, loader, uri, error); spl_append_uri(playlist, loader, uri);
success = true;
} else { } else {
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const Database &db = client.GetDatabaseOrThrow(); const Database &db = client.GetDatabaseOrThrow();

View File

@ -83,16 +83,12 @@ handle_add(Client &client, Request args, Response &r)
here */ here */
uri = ""; uri = "";
Error error; const auto located_uri = LocateUri(uri, &client
const auto located_uri = LocateUri(uri, &client,
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
nullptr, , nullptr
#endif #endif
error); );
switch (located_uri.type) { switch (located_uri.type) {
case LocatedUri::Type::UNKNOWN:
return print_error(r, error);
case LocatedUri::Type::ABSOLUTE: case LocatedUri::Type::ABSOLUTE:
case LocatedUri::Type::PATH: case LocatedUri::Type::PATH:
AddUri(client, located_uri); AddUri(client, located_uri);
@ -112,10 +108,7 @@ handle_addid(Client &client, Request args, Response &r)
const char *const uri = args.front(); const char *const uri = args.front();
const SongLoader loader(client); const SongLoader loader(client);
Error error; unsigned added_id = client.partition.AppendURI(loader, uri);
unsigned added_id = client.partition.AppendURI(loader, uri, error);
if (added_id == 0)
return print_error(r, error);
if (args.size == 2) { if (args.size == 2) {
unsigned to = args.ParseUnsigned(1); unsigned to = args.ParseUnsigned(1);

View File

@ -24,7 +24,6 @@
#include "tag/TagBuilder.hxx" #include "tag/TagBuilder.hxx"
#include "fs/Traits.hxx" #include "fs/Traits.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "DetachedSong.hxx" #include "DetachedSong.hxx"
#include <stdexcept> #include <stdexcept>
@ -49,7 +48,7 @@ playlist_check_load_song(DetachedSong &song, const SongLoader &loader)
DetachedSong *tmp; DetachedSong *tmp;
try { try {
tmp = loader.LoadSong(song.GetURI(), IgnoreError()); tmp = loader.LoadSong(song.GetURI());
} catch (const std::runtime_error &) { } catch (const std::runtime_error &) {
return false; return false;
} }

View File

@ -209,12 +209,13 @@ public:
unsigned AppendSong(PlayerControl &pc, DetachedSong &&song); unsigned AppendSong(PlayerControl &pc, DetachedSong &&song);
/** /**
* @return the new song id or 0 on error * Throws #std::runtime_error on error.
*
* @return the new song id
*/ */
unsigned AppendURI(PlayerControl &pc, unsigned AppendURI(PlayerControl &pc,
const SongLoader &loader, const SongLoader &loader,
const char *uri_utf8, const char *uri_utf8);
Error &error);
protected: protected:
void DeleteInternal(PlayerControl &pc, void DeleteInternal(PlayerControl &pc,

View File

@ -124,13 +124,9 @@ playlist::AppendSong(PlayerControl &pc, DetachedSong &&song)
unsigned unsigned
playlist::AppendURI(PlayerControl &pc, const SongLoader &loader, playlist::AppendURI(PlayerControl &pc, const SongLoader &loader,
const char *uri, const char *uri)
Error &error)
{ {
std::unique_ptr<DetachedSong> song(loader.LoadSong(uri, error)); std::unique_ptr<DetachedSong> song(loader.LoadSong(uri));
if (song == nullptr)
return 0;
return AppendSong(pc, std::move(*song)); return AppendSong(pc, std::move(*song));
} }

View File

@ -142,13 +142,13 @@ Client::GetStorage() const
return ::storage; return ::storage;
} }
bool void
Client::AllowFile(gcc_unused Path path_fs, gcc_unused Error &error) const Client::AllowFile(gcc_unused Path path_fs) const
{ {
/* always return false, so a SongLoader with a non-nullptr /* always fail, so a SongLoader with a non-nullptr
Client pointer will be regarded "insecure", while one with Client pointer will be regarded "insecure", while one with
client==nullptr will allow all files */ client==nullptr will allow all files */
return false; throw std::runtime_error("foo");
} }
static std::string static std::string