QTfrontend/ui/dialog/upload_video.cpp
changeset 7447 01111960a48d
child 7507 3032a5739fe1
equal deleted inserted replaced
7442:9bb6abdb5675 7447:01111960a48d
       
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include <QLineEdit>
       
    20 #include <QDialogButtonBox>
       
    21 #include <QPushButton>
       
    22 #include <QGridLayout>
       
    23 #include <QCheckBox>
       
    24 #include <QLabel>
       
    25 #include <QFrame>
       
    26 #include <QPlainTextEdit>
       
    27 #include <QSslError>
       
    28 #include <QUrl>
       
    29 #include <QNetworkAccessManager>
       
    30 #include <QNetworkRequest>
       
    31 #include <QNetworkReply>
       
    32 
       
    33 #include "upload_video.h"
       
    34 #include "hwconsts.h"
       
    35 
       
    36 // User-agent string used in http requests.
       
    37 static const QByteArray UserAgent = ("Hedgewars-QtFrontend/" + *cVersionString).toAscii();
       
    38 
       
    39 // This is developer key obtained from http://code.google.com/apis/youtube/dashboard/
       
    40 // If you are reusing this code outside Hedgewars, don't use this developer key,
       
    41 // obtain you own at http://code.google.com/apis/youtube/dashboard/
       
    42 static const QByteArray devKey = "AI39si5pKjxR0XgNIlmrEFF-LyYD31rps4g2O5dZTxLgD0fvJ2rHxrMrNFY8FYTZrzeI3VlaFVQLKfFnSBugvdZmy8vFzRDefQ";
       
    43 
       
    44 HWUploadVideoDialog::HWUploadVideoDialog(QWidget* parent, const QString &filename, QNetworkAccessManager* netManager) : QDialog(parent)
       
    45 {
       
    46     this->filename = filename;
       
    47     this->netManager = netManager;
       
    48 
       
    49     setWindowTitle(tr("Upload video"));
       
    50 
       
    51     // Google requires us to display this, see https://developers.google.com/youtube/terms
       
    52     QString GoogleNotice =
       
    53         "By clicking 'upload,' you certify that you own all rights to the content or that\n"
       
    54         "you are authorized by the owner to make the content publicly available on YouTube,\n"
       
    55         "and that it otherwise complies with the YouTube Terms of Service located at\n"
       
    56         "http://www.youtube.com/t/terms.";
       
    57 
       
    58     QGridLayout * layout = new QGridLayout(this);
       
    59 
       
    60     QLabel * lbLabel = new QLabel(this);
       
    61     lbLabel->setText(QLabel::tr(
       
    62                          "Please provide either the YouTube account name\n"
       
    63                          "or the email address associated with the Google Account."));
       
    64     layout->addWidget(lbLabel, 0, 0, 1, 2);
       
    65 
       
    66     lbLabel = new QLabel(this);
       
    67     lbLabel->setText(QLabel::tr("Account name (or email): "));
       
    68     layout->addWidget(lbLabel, 1, 0);
       
    69 
       
    70     leAccount = new QLineEdit(this);
       
    71     layout->addWidget(leAccount, 1, 1);
       
    72 
       
    73     lbLabel = new QLabel(this);
       
    74     lbLabel->setText(QLabel::tr("Password: "));
       
    75     layout->addWidget(lbLabel, 2, 0);
       
    76 
       
    77     lePassword = new QLineEdit(this);
       
    78     lePassword->setEchoMode(QLineEdit::Password);
       
    79     layout->addWidget(lePassword, 2, 1);
       
    80 
       
    81     cbSave = new QCheckBox(this);
       
    82     cbSave->setText(QCheckBox::tr("Save account name and password"));
       
    83     layout->addWidget(cbSave, 3, 0, 1, 2);
       
    84 
       
    85     QFrame * hr = new QFrame(this);
       
    86     hr->setFrameStyle(QFrame::HLine);
       
    87     hr->setLineWidth(3);
       
    88     hr->setFixedHeight(10);
       
    89     layout->addWidget(hr, 4, 0, 1, 2);
       
    90 
       
    91     lbLabel = new QLabel(this);
       
    92     lbLabel->setText(QLabel::tr("Video title: "));
       
    93     layout->addWidget(lbLabel, 5, 0);
       
    94 
       
    95     leTitle = new QLineEdit(this);
       
    96     leTitle->setText(filename);
       
    97     layout->addWidget(leTitle, 5, 1);
       
    98 
       
    99     lbLabel = new QLabel(this);
       
   100     lbLabel->setText(QLabel::tr("Video description: "));
       
   101     layout->addWidget(lbLabel, 6, 0, 1, 2);
       
   102 
       
   103     teDescription = new QPlainTextEdit(this);
       
   104     layout->addWidget(teDescription, 7, 0, 1, 2);
       
   105 
       
   106     hr = new QFrame(this);
       
   107         hr->setFrameStyle(QFrame::HLine);
       
   108         hr->setLineWidth(3);
       
   109         hr->setFixedHeight(10);
       
   110         layout->addWidget(hr, 8, 0, 1, 2);
       
   111 
       
   112     lbLabel = new QLabel(this);
       
   113     lbLabel->setText(GoogleNotice);
       
   114     layout->addWidget(lbLabel, 9, 0, 1, 2);
       
   115 
       
   116     labelLog = new QLabel(this);
       
   117     layout->addWidget(labelLog, 10, 0, 1, 2);
       
   118 
       
   119     QDialogButtonBox* dbbButtons = new QDialogButtonBox(this);
       
   120     btnUpload = dbbButtons->addButton(tr("Upload"), QDialogButtonBox::ActionRole);
       
   121     QPushButton * pbCancel = dbbButtons->addButton(QDialogButtonBox::Cancel);
       
   122     layout->addWidget(dbbButtons, 11, 0, 1, 2);
       
   123 
       
   124     connect(btnUpload, SIGNAL(clicked()), this, SLOT(upload()));
       
   125     connect(pbCancel, SIGNAL(clicked()), this, SLOT(reject()));
       
   126 }
       
   127 
       
   128 void HWUploadVideoDialog::log(const QString& text)
       
   129 {
       
   130     labelLog->setText(labelLog->text() + text);
       
   131 }
       
   132 
       
   133 void HWUploadVideoDialog::setEditable(bool editable)
       
   134 {
       
   135     leTitle->setEnabled(editable);
       
   136     leAccount->setEnabled(editable);
       
   137     lePassword->setEnabled(editable);
       
   138     btnUpload->setEnabled(editable);
       
   139 }
       
   140 
       
   141 void HWUploadVideoDialog::upload()
       
   142 {
       
   143     setEditable(false);
       
   144 
       
   145     labelLog->clear();
       
   146     log(tr("Authenticating at www.google.com... "));
       
   147 
       
   148     // Documentation is at https://developers.google.com/youtube/2.0/developers_guide_protocol_clientlogin#ClientLogin_Authentication
       
   149     QNetworkRequest request;
       
   150     request.setUrl(QUrl("https://www.google.com/accounts/ClientLogin"));
       
   151     request.setRawHeader("User-Agent", UserAgent);
       
   152     request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
       
   153 
       
   154     QString account(QUrl::toPercentEncoding(leAccount->text()));
       
   155     QString pass(QUrl::toPercentEncoding(lePassword->text()));
       
   156     QByteArray data = QString("Email=%1&Passwd=%2&service=youtube&source=Hedgewars").arg(account).arg(pass).toAscii();
       
   157 
       
   158     QNetworkReply *reply = netManager->post(request, data);
       
   159     connect(reply, SIGNAL(finished()), this, SLOT(authFinished()));
       
   160 }
       
   161 
       
   162 QString XmlEscape(const QString& str)
       
   163 {
       
   164     QString str2 = str;
       
   165     return "<![CDATA[" + str2.replace("]]>", "]]]]><![CDATA[>") + "]]>";
       
   166 }
       
   167 
       
   168 void HWUploadVideoDialog::authFinished()
       
   169 {
       
   170     QNetworkReply *reply = (QNetworkReply*)sender();
       
   171     reply->deleteLater();
       
   172 
       
   173     QByteArray answer = reply->readAll();
       
   174     QString authToken = "";
       
   175     QList<QByteArray> lines = answer.split('\n');
       
   176     foreach (const QByteArray& line, lines)
       
   177     {
       
   178         QString str(line);
       
   179         if (!str.startsWith("Auth=", Qt::CaseInsensitive))
       
   180             continue;
       
   181         str.remove(0, 5);
       
   182         authToken = str;
       
   183         break;
       
   184     }
       
   185     if (authToken.isEmpty())
       
   186     {
       
   187         log(tr("failed\n"));
       
   188         log(reply->errorString() + "\n");
       
   189         setEditable(true);
       
   190         return;
       
   191     }
       
   192     log(tr("Ok\n"));
       
   193 
       
   194     log(tr("Sending metadata... "));
       
   195 
       
   196     QByteArray auth = ("GoogleLogin auth=" + authToken).toAscii();
       
   197 
       
   198     // We have authenticated, now we can send metadata and start upload
       
   199     // Documentation is here: https://developers.google.com/youtube/2.0/developers_guide_protocol_resumable_uploads#Resumable_uploads
       
   200     QByteArray body =
       
   201             "<?xml version=\"1.0\"?>"
       
   202             "<entry xmlns=\"http://www.w3.org/2005/Atom\" "
       
   203                 "xmlns:media=\"http://search.yahoo.com/mrss/\" "
       
   204                 "xmlns:yt=\"http://gdata.youtube.com/schemas/2007\">"
       
   205                 "<media:group>"
       
   206                     "<yt:incomplete/>"
       
   207                     "<media:category "
       
   208                         "scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">Games"
       
   209                     "</media:category>"
       
   210                     "<media:title type=\"plain\">"
       
   211                         + XmlEscape(leTitle->text()).toUtf8() +
       
   212                     "</media:title>"
       
   213                 "</media:group>"
       
   214             "</entry>";
       
   215 
       
   216     QNetworkRequest request;
       
   217     request.setUrl(QUrl("http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads"));
       
   218     request.setRawHeader("User-Agent", UserAgent);
       
   219     request.setRawHeader("Authorization", auth);
       
   220     request.setRawHeader("GData-Version", "2");
       
   221     request.setRawHeader("X-GData-Key", "key=" + devKey);
       
   222     request.setRawHeader("Slug", filename.toUtf8());
       
   223     request.setRawHeader("Content-Type", "application/atom+xml; charset=UTF-8");
       
   224 
       
   225     reply = netManager->post(request, body);
       
   226     connect(reply, SIGNAL(finished()), this, SLOT(startUpload()));
       
   227 }
       
   228 
       
   229 void HWUploadVideoDialog::startUpload()
       
   230 {
       
   231     QNetworkReply *reply = (QNetworkReply*)sender();
       
   232     reply->deleteLater();
       
   233 
       
   234     location = QString::fromAscii(reply->rawHeader("Location"));
       
   235     if (location.isEmpty())
       
   236     {
       
   237         log(tr("failed\n"));
       
   238         log(reply->errorString() + "\n");
       
   239         setEditable(true);
       
   240         return;
       
   241     }
       
   242 
       
   243     log(tr("Ok\n"));
       
   244     accept();
       
   245 }