Exemplo n.º 1
0
void SubsonicService::onPingFinished()
{
  QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
  reply->deleteLater();

  if (reply->error() != QNetworkReply::NoError)
  {
    login_state_ = LoginState_BadServer;
    qLog(Error) << "Failed to connect ("
                << Utilities::EnumToString(QNetworkReply::staticMetaObject, "NetworkError", reply->error())
                << "):" << reply->errorString();
  }
  else
  {
    QXmlStreamReader reader(reply);
    reader.readNextStartElement();
    QStringRef status = reader.attributes().value("status");
    if (status == "ok")
    {
      login_state_ = LoginState_Loggedin;
    }
    else
    {
      reader.readNextStartElement();
      int error = reader.attributes().value("code").toString().toInt();
      qLog(Error) << "Subsonic error ("
                  << Utilities::EnumToString(SubsonicService::staticMetaObject, "ApiError", error)
                  << "):" << reader.attributes().value("message").toString();
      switch (error)
      {
      // "Parameter missing" for "ping" is always blank username or password
      case ApiError_ParameterMissing:
      case ApiError_BadCredentials:
        login_state_ = LoginState_BadCredentials;
        break;
      case ApiError_OutdatedClient:
        login_state_ = LoginState_OutdatedClient;
        break;
      case ApiError_OutdatedServer:
        login_state_ = LoginState_OutdatedServer;
        break;
      case ApiError_Unlicensed:
        login_state_ = LoginState_Unlicensed;
        break;
      default:
        login_state_ = LoginState_OtherError;
        break;
      }
    }
  }
  qLog(Debug) << "Login state changed:"
              << Utilities::EnumToString(SubsonicService::staticMetaObject, "LoginState", login_state_);
  emit LoginStateChanged(login_state_);
}
Exemplo n.º 2
0
SubsonicService::SubsonicService(InternetModel *parent)
  : InternetService(kServiceName, parent, parent),
    network_(new QNetworkAccessManager(this)),
    http_url_handler_(new SubsonicUrlHandler(this, this)),
    https_url_handler_(new SubsonicHttpsUrlHandler(this, this)),
    login_state_(LoginState_OtherError),
    item_lookup_()
{
  model()->player()->RegisterUrlHandler(http_url_handler_);
  model()->player()->RegisterUrlHandler(https_url_handler_);
  connect(this, SIGNAL(LoginStateChanged(SubsonicService::LoginState)),
          SLOT(onLoginStateChanged(SubsonicService::LoginState)));
}
Exemplo n.º 3
0
void SubsonicService::Login() {
  // Recreate fresh network state, otherwise old HTTPS settings seem to get reused
  network_->deleteLater();
  network_ = new QNetworkAccessManager(this);
  network_->setCookieJar(new QNetworkCookieJar(network_));
  // Forget login state whilst waiting
  login_state_ = LoginState_Unknown;

  if (IsConfigured()) {
    // Ping is enough to check credentials
    Ping();
  } else {
    login_state_ = LoginState_IncompleteCredentials;
    emit LoginStateChanged(login_state_);
  }
}
Exemplo n.º 4
0
SubsonicService::SubsonicService(Application* app, InternetModel* parent)
  : InternetService(kServiceName, app, parent, parent),
    network_(new QNetworkAccessManager(this)),
    url_handler_(new SubsonicUrlHandler(this, this)),
    scanner_(new SubsonicLibraryScanner(this, this)),
    load_database_task_id_(0),
    context_menu_(NULL),
    root_(NULL),
    library_backend_(NULL),
    library_model_(NULL),
    library_filter_(NULL),
    library_sort_model_(new QSortFilterProxyModel(this)),
    total_song_count_(0),
    login_state_(LoginState_OtherError),
    redirect_count_(0) {
  app_->player()->RegisterUrlHandler(url_handler_);

  connect(scanner_, SIGNAL(ScanFinished()),
          SLOT(ReloadDatabaseFinished()));

  library_backend_ = new LibraryBackend;
  library_backend_->moveToThread(app_->database()->thread());
  library_backend_->Init(app_->database(),
                         kSongsTable,
                         QString::null,
                         QString::null,
                         kFtsTable);
  connect(library_backend_, SIGNAL(TotalSongCountUpdated(int)),
          SLOT(UpdateTotalSongCount(int)));

  library_model_ = new LibraryModel(library_backend_, app_, this);
  library_model_->set_show_various_artists(false);
  library_model_->set_show_smart_playlists(false);

  library_filter_ = new LibraryFilterWidget(0);
  library_filter_->SetSettingsGroup(kSettingsGroup);
  library_filter_->SetLibraryModel(library_model_);
  library_filter_->SetFilterHint(tr("Search Subsonic"));
  library_filter_->SetAgeFilterEnabled(false);

  library_sort_model_->setSourceModel(library_model_);
  library_sort_model_->setSortRole(LibraryModel::Role_SortText);
  library_sort_model_->setDynamicSortFilter(true);
  library_sort_model_->setSortLocaleAware(true);
  library_sort_model_->sort(0);

  connect(this, SIGNAL(LoginStateChanged(SubsonicService::LoginState)),
          SLOT(OnLoginStateChanged(SubsonicService::LoginState)));

  context_menu_ = new QMenu;
  context_menu_->addActions(GetPlaylistActions());
  context_menu_->addSeparator();
  context_menu_->addAction(
      IconLoader::Load("view-refresh"),
      tr("Refresh catalogue"),
      this, SLOT(ReloadDatabase()));
  QAction* config_action = context_menu_->addAction(
      IconLoader::Load("configure"),
      tr("Configure Subsonic..."),
      this, SLOT(ShowConfig()));
  context_menu_->addSeparator();
  context_menu_->addMenu(library_filter_->menu());

  library_filter_->AddMenuAction(config_action);

  app_->global_search()->AddProvider(new LibrarySearchProvider(
      library_backend_,
      tr("Subsonic"),
      "subsonic",
      QIcon(":/providers/subsonic.png"),
      true, app_, this));
}
Exemplo n.º 5
0
void SubsonicService::OnPingFinished(QNetworkReply* reply) {
  reply->deleteLater();

  if (reply->error() != QNetworkReply::NoError) {
    switch(reply->error()) {
      case QNetworkReply::ConnectionRefusedError:
        login_state_ = LoginState_ConnectionRefused;
        break;
      case QNetworkReply::HostNotFoundError:
        login_state_ = LoginState_HostNotFound;
        break;
      case QNetworkReply::TimeoutError:
        login_state_ = LoginState_Timeout;
        break;
      case QNetworkReply::SslHandshakeFailedError:
        login_state_ = LoginState_SslError;
        break;
      default: //Treat uncaught error types here as generic
        login_state_ = LoginState_BadServer;
        break;
    }
    qLog(Error) << "Failed to connect ("
                << Utilities::EnumToString(QNetworkReply::staticMetaObject, "NetworkError", reply->error())
                << "):" << reply->errorString();
  } else {
    QXmlStreamReader reader(reply);
    reader.readNextStartElement();
    QStringRef status = reader.attributes().value("status");
    int http_status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if (status == "ok") {
      login_state_ = LoginState_Loggedin;
    } else if (http_status_code >= 300 && http_status_code <= 399) {
      // Received a redirect status code, follow up on it.
      QUrl redirect_url =
          reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
      if (redirect_url.isEmpty()) {
        qLog(Debug) << "Received HTTP code " << http_status_code << ", but no URL";
        login_state_ = LoginState_RedirectNoUrl;
      } else {
        redirect_count_++;
        qLog(Debug) << "Redirect receieved to "
                    << redirect_url.toString(QUrl::RemoveQuery)
                    << ", current redirect count is "
                    << redirect_count_;
        if (redirect_count_ <= kMaxRedirects) {
          working_server_ = ScrubUrl(redirect_url).toString(QUrl::RemoveQuery);
          Ping();
          // To avoid the LoginStateChanged, as it will come from the recursive request.
          return;
        } else {
          // Redirect limit exceeded
          login_state_ = LoginState_RedirectLimitExceeded;
        }
      }
    } else {
      reader.readNextStartElement();
      int error = reader.attributes().value("code").toString().toInt();
      qLog(Error) << "Subsonic error ("
                  << Utilities::EnumToString(SubsonicService::staticMetaObject, "ApiError", error)
                  << "):" << reader.attributes().value("message").toString();
      switch (error) {
        // "Parameter missing" for "ping" is always blank username or password
        case ApiError_ParameterMissing:
        case ApiError_BadCredentials:
          login_state_ = LoginState_BadCredentials;
          break;
        case ApiError_OutdatedClient:
          login_state_ = LoginState_OutdatedClient;
          break;
        case ApiError_OutdatedServer:
          login_state_ = LoginState_OutdatedServer;
          break;
        case ApiError_Unlicensed:
          login_state_ = LoginState_Unlicensed;
          break;
        default:
          login_state_ = LoginState_OtherError;
          break;
      }
    }
  }
  qLog(Debug) << "Login state changed:"
              << Utilities::EnumToString(SubsonicService::staticMetaObject, "LoginState", login_state_);
  emit LoginStateChanged(login_state_);
}