1 /****************************************************************************************
2  * Copyright (c) 2009 Nikolaj Hald Nielsen <nhn@kde.org>                                *
3  *                                                                                      *
4  * This program is free software; you can redistribute it and/or modify it under        *
5  * the terms of the GNU General Public License as published by the Free Software        *
6  * Foundation; either version 2 of the License, or (at your option) any later           *
7  * version.                                                                             *
8  *                                                                                      *
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12  *                                                                                      *
13  * You should have received a copy of the GNU General Public License along with         *
14  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15  ****************************************************************************************/
16 
17 #include "AmarokUrl.h"
18 
19 #include "AmarokUrlHandler.h"
20 #include "BookmarkGroup.h"
21 #include "core-impl/storage/StorageManager.h"
22 #include "core/support/Debug.h"
23 #include <core/storage/SqlStorage.h>
24 
25 #include <QUrl>
26 #include <QUrlQuery>
27 
AmarokUrl()28 AmarokUrl::AmarokUrl()
29     : m_id( -1 )
30     , m_parent( 0 )
31 {}
32 
AmarokUrl(const QString & urlString,const BookmarkGroupPtr & parent)33 AmarokUrl::AmarokUrl( const QString & urlString, const BookmarkGroupPtr &parent )
34     : m_id( -1 )
35     , m_parent( parent )
36 {
37     initFromString( urlString );
38 }
39 
AmarokUrl(const QStringList & resultRow,const BookmarkGroupPtr & parent)40 AmarokUrl::AmarokUrl( const QStringList & resultRow, const BookmarkGroupPtr &parent )
41     : m_parent( parent )
42 {
43     m_id = resultRow[0].toInt();
44     m_name = resultRow[2];
45     const QString urlString = resultRow[3];
46     m_description = resultRow[4];
47     m_customValue = resultRow[5];
48 
49     initFromString( urlString );
50 }
51 
~AmarokUrl()52 AmarokUrl::~AmarokUrl()
53 {}
54 
initFromString(const QString & urlString)55 void AmarokUrl::initFromString( const QString & urlString )
56 {
57     //first, strip amarok://
58     QString strippedUrlString = urlString;
59     strippedUrlString = strippedUrlString.replace( QLatin1String("amarok://"), QLatin1String("") );
60 
61     //separate path from arguments
62     QStringList parts = strippedUrlString.split( QLatin1Char('?') );
63 
64     QString commandAndPath = parts.at( 0 );
65 
66     QString argumentsString;
67     if ( parts.size() == 2 )
68         argumentsString = parts.at( 1 );
69 
70     if ( !argumentsString.isEmpty() )
71     {
72         parts = argumentsString.split( '&' );
73 
74         foreach( const QString &argument, parts )
75         {
76 
77             QStringList argParts = argument.split( '=' );
78             debug() << "argument: " << argument << " unescaped: " << unescape( argParts.at( 1 ) );
79             setArg( argParts.at( 0 ), unescape( argParts.at( 1 ) ) );
80         }
81     }
82 
83     //get the command
84 
85     parts = commandAndPath.split( QLatin1Char('/') );
86     m_command = parts.takeFirst();
87 
88     m_path = parts.join( QLatin1Char('/') );
89 
90     m_path = unescape( m_path );
91 }
92 
setCommand(const QString & command)93 void AmarokUrl::setCommand( const QString & command )
94 {
95     m_command = command;
96 }
97 
command() const98 QString AmarokUrl::command() const
99 {
100         return m_command;
101 }
102 
103 QString
prettyCommand() const104 AmarokUrl::prettyCommand() const
105 {
106     return The::amarokUrlHandler()->prettyCommand( command() );
107 }
108 
args() const109 QMap<QString, QString> AmarokUrl::args() const
110 {
111     return m_arguments;
112 }
113 
setArg(const QString & name,const QString & value)114 void AmarokUrl::setArg( const QString &name, const QString &value )
115 {
116     m_arguments.insert( name, value );
117 }
118 
run()119 bool AmarokUrl::run()
120 {
121     DEBUG_BLOCK
122     return The::amarokUrlHandler()->run( *this );
123 }
124 
url() const125 QString AmarokUrl::url() const
126 {
127     QUrl url;
128     url.setScheme( QStringLiteral("amarok") );
129     url.setHost( m_command );
130     url.setPath( '/' + m_path ); // the path must begin by /
131     QUrlQuery query;
132 
133     foreach( const QString &argName, m_arguments.keys() )
134         query.addQueryItem( argName, m_arguments[argName] );
135 
136     url.setQuery( query );
137     return url.toEncoded();
138 }
139 
saveToDb()140 bool AmarokUrl::saveToDb()
141 {
142     DEBUG_BLOCK
143 
144     if ( isNull() )
145         return false;
146 
147     const int parentId = m_parent ? m_parent->id() : -1;
148 
149     auto sql =  StorageManager::instance()->sqlStorage();
150 
151     if( m_id != -1 )
152     {
153         //update existing
154         debug() << "Updating bookmark";
155         QString query = QStringLiteral("UPDATE bookmarks SET parent_id=%1, name='%2', url='%3', description='%4', custom='%5' WHERE id=%6;");
156         query = query.arg( QString::number( parentId ), sql->escape( m_name ), sql->escape( url() ),
157                            sql->escape( m_description ), sql->escape( m_customValue ), QString::number( m_id ) );
158         StorageManager::instance()->sqlStorage()->query( query );
159     }
160     else
161     {
162         //insert new
163         debug() << "Creating new bookmark in the db";
164         QString query = QStringLiteral("INSERT INTO bookmarks ( parent_id, name, url, description, custom ) VALUES ( %1, '%2', '%3', '%4', '%5' );");
165         query = query.arg( QString::number( parentId ), sql->escape( m_name ), sql->escape( url() ),
166                            sql->escape( m_description ), sql->escape( m_customValue ) );
167         m_id = StorageManager::instance()->sqlStorage()->insert( query, nullptr );
168     }
169 
170     return true;
171 }
172 
setName(const QString & name)173 void AmarokUrl::setName( const QString & name )
174 {
175     m_name = name;
176 }
177 
name() const178 QString AmarokUrl::name() const
179 {
180     return m_name;
181 }
182 
setDescription(const QString & description)183 void AmarokUrl::setDescription( const QString & description )
184 {
185     m_description = description;
186 }
187 
description() const188 QString AmarokUrl::description() const
189 {
190     return m_description;
191 }
192 
removeFromDb()193 void AmarokUrl::removeFromDb()
194 {
195     QString query = QStringLiteral("DELETE FROM bookmarks WHERE id=%1");
196     query = query.arg( QString::number( m_id ) );
197     StorageManager::instance()->sqlStorage()->query( query );
198 }
199 
rename(const QString & name)200 void AmarokUrl::rename( const QString &name )
201 {
202     m_name = name;
203     if ( m_id != -1 )
204         saveToDb();
205 }
206 
reparent(const BookmarkGroupPtr & parent)207 void AmarokUrl::reparent( const BookmarkGroupPtr &parent )
208 {
209     m_parent = parent;
210     saveToDb();
211 }
212 
setCustomValue(const QString & custom)213 void AmarokUrl::setCustomValue( const QString & custom )
214 {
215     m_customValue = custom;
216 }
217 
customValue() const218 QString AmarokUrl::customValue() const
219 {
220     return m_customValue;
221 }
222 
escape(const QString & in)223 QString AmarokUrl::escape( const QString & in )
224 {
225     return QUrl::toPercentEncoding( in.toUtf8() );
226 }
227 
unescape(const QString & in)228 QString AmarokUrl::unescape( const QString & in )
229 {
230     return QUrl::fromPercentEncoding( in.toUtf8() );
231 }
232 
isNull() const233 bool AmarokUrl::isNull() const
234 {
235     return m_command.isEmpty();
236 }
237 
path() const238 QString AmarokUrl::path() const
239 {
240     return m_path;
241 }
242 
setPath(const QString & path)243 void AmarokUrl::setPath( const QString &path )
244 {
245     m_path = path;
246 }
247 
248 
249 
250