bool RequestHandler::handle_request(const Http::Request& req, Http::Reply& rep)
{
    using namespace Http;

    if (!enabled_) {
        fill_reply_disabled(rep);
        return true;
    }

    try {
        const PlaylistID playlist_id = getPlaylistID(req.uri);
        
        if (IPlaylistUpdateManager* playlist_update_manager  = dynamic_cast<IPlaylistUpdateManager*>(&aimp_manager_)) {
            playlist_update_manager->lockPlaylist(playlist_id);
        }
        auto unlock_playlist = [this] (PlaylistID playlist_id) {
            if (IPlaylistUpdateManager* playlist_update_manager  = dynamic_cast<IPlaylistUpdateManager*>(&aimp_manager_)) {
                playlist_update_manager->unlockPlaylist(playlist_id);
            }
        };
        ON_BLOCK_EXIT(unlock_playlist, playlist_id);

        for (auto field_it : req.mpfd_parser->GetFieldsMap()) {
            const MPFD::Field& field_const = *field_it.second;
            MPFD::Field& field = const_cast<MPFD::Field&>(field_const);

            switch (field.GetType()) {
            case MPFD::Field::FileType:
                {
                const std::wstring filename = StringEncoding::utf8_to_utf16( field.GetFileName() );
                const fs::wpath path = fs::path(field.GetTempFileName()).parent_path() / filename;
                if (!fileTypeSupported(path.extension().native(), aimp_manager_)) {
                    continue;
                }
                fs::copy_file(field.GetTempFileName(), path, fs::copy_option::overwrite_if_exists); // can't use rename here since parser will close file in Field's dtor.
                aimp_manager_.addFileToPlaylist(path, playlist_id);
                // we should not erase file since AIMP will use it.
                //fs::remove(path);
                break;
                }
            case MPFD::Field::TextType:
                {
                aimp_manager_.addURLToPlaylist(field.GetTextTypeContent(), playlist_id);
                break;
                }
            default:
                assert(!"unexpected type");
                break;
            }
        }
        rep = Reply::stock_reply(Reply::ok);
    } catch (MPFD::Exception&) {
        rep = Reply::stock_reply(Reply::bad_request);
    } catch (std::exception& e) {
        (void)e;
        rep = Reply::stock_reply(Reply::forbidden);
    }
    return true;
}
bool Platform::pathIsShortcut(const boost::filesystem::wpath& path_to_investigate) {
  std::string ext = FB::wstring_to_utf8(path_to_investigate.extension());
  std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
  return (ext == ".lnk");
}