Development/Tutorials/KNewStuffSecure: Difference between revisions

From KDE TechBase
(Proofreading)
(Mark for archiving)
 
(8 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{Improve}}
{{Archived}}
{{KDE3}}


== Resource sharing ==
== Resource sharing ==
Line 6: Line 7:
Starting with KDE 3.4 and with the introduction of the KNewStuffSecure class this problems are solved. With this technology the resources can be digitally signed, an md5sum is calculated for them, so both the uploaded and downloaded resources can be verified whether they come from a safe source and person or not.
Starting with KDE 3.4 and with the introduction of the KNewStuffSecure class this problems are solved. With this technology the resources can be digitally signed, an md5sum is calculated for them, so both the uploaded and downloaded resources can be verified whether they come from a safe source and person or not.


This tutorial will explain how to use KNewStuffSecure in your application to enable downloading and uploading secured resources. It will not explain the usage of KNewStuff itself and how you can set up a resource repository on the server. These informations can be found in the KNewStuff <a href="http://developer.kde.org/documentation/library/cvs-api/knewstuff/html/">API documentation</a>, in the <a href="http://www.kstuff.org/docs/tutorial/">KNewStuff tutorial</a> and in the sources: <strong><a href="http://webcvs.kde.org/kdelibs/knewstuff/README.knewstuff?view=markup">kdelibs/knewstuff/README.knewstuff</a></strong> and <strong><a href="http://webcvs.kde.org/kdelibs/knewstuff/data">kdelibs/knewstuff/data</a></strong> .</p>
This tutorial will explain how to use KNewStuffSecure in your application to enable downloading and uploading secured resources. It will not explain the usage of KNewStuff itself and how you can set up a resource repository on the server. These informations can be found in the KNewStuff [http://developer.kde.org/documentation/library/cvs-api/knewstuff/html/ API documentation], in the [http://www.kstuff.org/docs/tutorial/ KNewStuff tutorial] and in the sources: [http://webcvs.kde.org/kdelibs/knewstuff/README.knewstuff?view=markup kdelibs/knewstuff/README.knewstuff] and [http://webcvs.kde.org/kdelibs/knewstuff/data kdelibs/knewstuff/data].


<hr />
<hr />
<h2>General information</h2>


<p>Using KNewStuff itself is quite simple, and I tried to make KNewStuffSecure not
== General information ==
  more complicated. The only extra requirement is to have <strong>gpg</strong> installed in your
  path, and for uploading of course it is preferred if you already have a GPG key
that you can use for resource signing.</p>


<p>As <strong>gpg</strong> is not a compilation time requirement, it is suggested that you check on application startup for its presence and warn the user what he misses without it. Of course the check is performed by KNewStuffSecure as well, but I find it muchnicer to check for runtime dependencies on startup.</p>
Using KNewStuff itself is quite simple, and I tried to make KNewStuffSecure not more complicated. The only extra requirement is to have <strong>gpg</strong> installed in your {{path|$PATH}}, and for uploading of course it is preferred if you already have a GPG key that you can use for resource signing.
 
As '''gpg''' is not a compilation time requirement, it is suggested that you check on application startup for its presence and warn the user what he misses without it. Of course the check is performed by KNewStuffSecure as well, but I find it muchnicer to check for runtime dependencies on startup.


<hr />
<hr />
<h2>Downloading resources</h2>
== Downloading resources ==
<p>The first thing you must to is to subclass the KNewStuffSecure class and implement the installResource method, which is a pure virtual method in KNewStuffSecure. Here is an example of what you should put in a header file:</p>
The first thing you must to is to subclass the {{class|KNewStuffSecure}} class and implement the installResource method, which is a pure virtual method in KNewStuffSecure. Here is an example of what you should put in a header file:
<div class="codeBox">
<syntaxhighlight lang="cpp-qt">
<pre>
#include <knewstuff/knewstuffsecure.h>
  #include &lt;knewstuff/knewstuffsecure.h&gt;
 
   class MyNewStuff: public KNewStuffSecure
class MyNewStuff: public KNewStuffSecure
{
  Q_OBJECT
 
  public:
    MyNewStuff(const QString &type,  QWidget *parentWidget=0)
      : KNewStuffSecure(type, parentWidget){};
    ~MyNewStuff() {};
    
  private:
    virtual void installResource();
};
</syntaxhighlight>
 
In order to know what you should do in installResource() it is important to understand the structure of the resource you get via KNewStuffSecure. The resource is a gzipped tarball, let's call it {{path|resource.tar.gz}}. The {{path|resource.tar.gz}} contains three files:
 
{| border="1"
! Filename !! Description
|-
| {{path|data.tar.gz}} || another tarball containing the actual data to be installed. The name is not fixed, it can be anything like {{path|cards.tgz}}, {{path|greetings.tar.gz}} or whatever.
|-
| signature || holds the signature for {{path|data.tar.gz}}
|-
| md5sum || holds the MD5 sum for the {{path|data.tar.gz}}
|}
 
In the implementation file you have to process the {{path|data.tar.gz}} only, the rest is handled by KNewStuffSecure. If installing the resource means that you put the downloaded file(s) from {{path|data.tar.gz}} into a directory, the implementation of MyNewStuff looks like:
 
<syntaxhighlight lang="cpp-qt">
void MyNewStuff::installResource()
{
  KTar tar(m_tarName, "application/x-gzip" );
  if (tar.open(IO_ReadOnly))
   {
   {
     Q_OBJECT
     const KArchiveDirectory *directory = tar.directory();
      
     QString resDir =KGlobal::dirs()->saveLocation("data" ) + "appname/stuff/";
     public:
     directory->copyTo(resDir, true);
      MyNewStuff(const QString &type, QWidget *parentWidget=0)
    tar.close();
        :KNewStuffSecure(type, parentWidget){};
  } else
      ~MyNewStuff() {};
    KMessageBox::error(parentWidget(), i18n("There was an error with the
      
     downloaded resource tarball file. Possible causes are damaged archive or
     private:
     invalid directory structure in the archive." ),
      virtual void installResource();
    i18n("Resource Installation Error" ));
  };
}
</pre>
</syntaxhighlight>
</div>
 
<p>In order to know what you should do in installResource() it is important to understand the structure of the resource you get via KNewStuffSecure. The resource is a gzipped tarball, let's call it resource.tar.gz. The resource.tar.gz contains three files:
As you can see the name of the resource tarball you have to install is in
</p>
"m_tarName". The above code installs the files from m_tarName to {{path|$KDEHOME/share/appname/stuff}}. Of course, you must provide the real appname there.
<table frame="border" border="1">
 
  <thead>
You are free to do other installation methods, depending on your needs. In some cases it may be just enough to copy the resource tarball somewhere. This part of the code depends completely on the type of the resource and your application.
    <tr>
 
      <th>Filename</th>
Now how to initiate a download? You have to do three things:
      <th>Description</th>
* create a MyNewStuff object
    </tr>
* connect the signal installFinished() to a slot to do things what you want after the install is done
  </thead>
* call downloadResource() for the MyNewStuff object
  <tbody>
 
    <tr>
Example:
      <td>data.tar.gz</td>
<syntaxhighlight lang="cpp-qt">
      <td>another tarball containing the actual data to be installed. The 
void MyApp::slotDownloadResource()
              name is not fixed, it can be anything like cards.tgz,
{
              greetings.tar.gz or whatever.</td>
  if (!m_newStuff)
    </tr>
    <tr>
      <td>signature</td>
      <td>holds the signature for data.tar.gz</td>
    </tr>
    <tr>
      <td>md5sum</td>
      <td>holds the MD5 sum for the data.tar.gz</td>
    </tr>
  </tbody>
</table>
<p>In the implementation file you have to process the data.tar.gz only, the rest is
handled by KNewStuffSecure. If installing the resource means that you put the
downloaded file(s) from data.tar.gz into a directory, the implementation of
MyNewStuff looks like:
</p>
<div class="codeBox">
<pre>
  void MyNewStuff::installResource()
   {
   {
     bool ok = true;
     m_newStuff = new MyNewStuff("appname/resourcetype", this);
    KTar tar(m_tarName, "application/x-gzip" );
     connect(m_newStuff, SIGNAL(installFinished()), this, SLOT(slotResourceInstalled()));
     if (tar.open(IO_ReadOnly))
    {
      const KArchiveDirectory *directory = tar.directory();
      QString resDir =KGlobal::dirs()->saveLocation("data" ) + "appname/stuff/";
      directory->copyTo(resDir, true);
      tar.close();
    } else
      ok = false;
 
    if (!ok)
      KMessageBox::error(parentWidget(), i18n("There was an error with the
      downloaded resource tarball file. Possible causes are damaged archive or
      invalid directory structure in the archive." ),
      i18n("Resource Installation Error" ));
   }
   }
</pre>
   m_newStuff->downloadResource();
</div>
}
<p>As you can see the name of the resource tarball you have to install is in
</syntaxhighlight>
"m_tarName". The above code installs the files from m_tarName to
 
<strong>$KDEHOME/share/appname/stuff</strong>. Of course, you must provide the real appname there.
Just a note: ''"appname/resourcetype"'' is in free form, it identifies the type of the resource. See the standard KNewStuff documentation for details.
</p>
<p>You are free to do other installation methods, depending on your needs. In some
cases it may be just enough to copy the resource tarball somewhere. This part
of the code depends completely on the type of the resource and your application.
</p>
<p>Now how to initiate a download? You have to do three things:
</p>
<ul>
<li>create a MyNewStuff object</li>
<li>connect the signal installFinished() to a slot to do things what you want after the install is done</li>
<li>call downloadResource() for the MyNewStuff object</li>
</ul>
<p>Example:
</p>
<div class="codeBox">
<pre>
   void MyApp::slotDownloadResource()
  {
    if (!m_newStuff)
    {
      m_newStuff = new MyNewStuff("appname/resourcetype", this);
      connect(m_newStuff, SIGNAL(installFinished()), this, SLOT(slotResourceInstalled()));
    }
    m_newStuff->downloadResource();
  }
</pre>
</div>
<p>Just a note: <em>"appname/resourcetype"</em> is in free form, it identifies the type of the resource. See the standard KNewStuff documentation for details.
</p>


<hr />
<hr />
<h2>Uploading resources</h2>
 
<p>Uploading is simple as well. You just have to create
== Uploading resources ==
the data.tar.gz (which is specific for your application) and call uploadResource(fileName), where fileName points to the created data tarball.  
Uploading is simple as well. You just have to create the {{path|data.tar.gz}} (which is specific for your application) and call uploadResource(fileName), where fileName points to the created data tarball.  
</p>
 
<p>Example:</p>
Example:
<div class="codeBox">
<syntaxhighlight lang="cpp-qt">
<pre>
void MyApp::slotUploadResource()
  void MyApp::slotUploadResource()
{
  {
  QString fileName = createUploadResource();
    QString fileName = createUploadResource();
  if (!m_newStuff)
    if (!m_newStuff)
    m_newStuff = new MyNewStuff("application/resourcetype", this);
      m_newStuff = new MyNewStuff("application/resourcetype", this);
  m_newStuff->uploadResource(fileName);
    m_newStuff->uploadResource(fileName);
}   
  }   
</syntaxhighlight>
</pre>
 
</div>
Here createUploadResource() creates the data tarball and returns the name with path to the created tarball.
<p>Here createUploadResource() creates the data tarball and returns the name with path to the created tarball.
 
</p>
That is all. I hope you will find this tutorial useful.
<p>That is all. I hope you will find this tutorial useful.</p>

Latest revision as of 13:23, 31 May 2019


This page has been archived
The information on this page is outdated or no longer in use but is kept for historical purposes. Please see the Category:Archives for similar pages.
Tip
Note: This page deals with content related to KDE 3. If you are developing for KDE 4, this information might not be valid anymore.


Resource sharing

Many applications work with external resources which gives them the freedom to change or extend the behavior without requiring to change the application code itself. Others are extensible with the help of binary plugins. All these external resources should be provided in a way to the user, and the most common way is to put them on the homepage of the application, which works, but it is not so convenient to the final user to get the updates. It is much easier to get them from inside the application. Luckily KDE has the corresponding technology called KNewStuff which not only makes possible to download updates and resources, but if the application supports it, it is even possible to share a resource created by the user with other users. KNewStuff has a weak point though, that you cannot really know who created a resource when downloading, nor the maintainer of the resource repository can know who created the resource that was uploaded, and there is no corruption checking either.

Starting with KDE 3.4 and with the introduction of the KNewStuffSecure class this problems are solved. With this technology the resources can be digitally signed, an md5sum is calculated for them, so both the uploaded and downloaded resources can be verified whether they come from a safe source and person or not.

This tutorial will explain how to use KNewStuffSecure in your application to enable downloading and uploading secured resources. It will not explain the usage of KNewStuff itself and how you can set up a resource repository on the server. These informations can be found in the KNewStuff API documentation, in the KNewStuff tutorial and in the sources: kdelibs/knewstuff/README.knewstuff and kdelibs/knewstuff/data.


General information

Using KNewStuff itself is quite simple, and I tried to make KNewStuffSecure not more complicated. The only extra requirement is to have gpg installed in your $PATH, and for uploading of course it is preferred if you already have a GPG key that you can use for resource signing.

As gpg is not a compilation time requirement, it is suggested that you check on application startup for its presence and warn the user what he misses without it. Of course the check is performed by KNewStuffSecure as well, but I find it muchnicer to check for runtime dependencies on startup.


Downloading resources

The first thing you must to is to subclass the KNewStuffSecure class and implement the installResource method, which is a pure virtual method in KNewStuffSecure. Here is an example of what you should put in a header file:

#include <knewstuff/knewstuffsecure.h>

class MyNewStuff: public KNewStuffSecure
{
  Q_OBJECT
  
  public:
    MyNewStuff(const QString &type,  QWidget *parentWidget=0)
      : KNewStuffSecure(type, parentWidget){};
    ~MyNewStuff() {};
  
  private:
    virtual void installResource();
};

In order to know what you should do in installResource() it is important to understand the structure of the resource you get via KNewStuffSecure. The resource is a gzipped tarball, let's call it resource.tar.gz. The resource.tar.gz contains three files:

Filename Description
data.tar.gz another tarball containing the actual data to be installed. The name is not fixed, it can be anything like cards.tgz, greetings.tar.gz or whatever.
signature holds the signature for data.tar.gz
md5sum holds the MD5 sum for the data.tar.gz

In the implementation file you have to process the data.tar.gz only, the rest is handled by KNewStuffSecure. If installing the resource means that you put the downloaded file(s) from data.tar.gz into a directory, the implementation of MyNewStuff looks like:

void MyNewStuff::installResource()
{
  KTar tar(m_tarName, "application/x-gzip" );
  if (tar.open(IO_ReadOnly))
  {
    const KArchiveDirectory *directory = tar.directory();
    QString resDir =KGlobal::dirs()->saveLocation("data" ) + "appname/stuff/";
    directory->copyTo(resDir, true);
    tar.close();
  } else
    KMessageBox::error(parentWidget(), i18n("There was an error with the
    downloaded resource tarball file. Possible causes are damaged archive or
    invalid directory structure in the archive." ), 
    i18n("Resource Installation Error" ));
}

As you can see the name of the resource tarball you have to install is in "m_tarName". The above code installs the files from m_tarName to $KDEHOME/share/appname/stuff. Of course, you must provide the real appname there.

You are free to do other installation methods, depending on your needs. In some cases it may be just enough to copy the resource tarball somewhere. This part of the code depends completely on the type of the resource and your application.

Now how to initiate a download? You have to do three things:

  • create a MyNewStuff object
  • connect the signal installFinished() to a slot to do things what you want after the install is done
  • call downloadResource() for the MyNewStuff object

Example:

void MyApp::slotDownloadResource()
{
  if (!m_newStuff)
  {
    m_newStuff = new MyNewStuff("appname/resourcetype", this);
    connect(m_newStuff, SIGNAL(installFinished()), this, SLOT(slotResourceInstalled()));
  }
  m_newStuff->downloadResource();
}

Just a note: "appname/resourcetype" is in free form, it identifies the type of the resource. See the standard KNewStuff documentation for details.


Uploading resources

Uploading is simple as well. You just have to create the data.tar.gz (which is specific for your application) and call uploadResource(fileName), where fileName points to the created data tarball.

Example:

void MyApp::slotUploadResource()
{
  QString fileName = createUploadResource();
  if (!m_newStuff)
    m_newStuff = new MyNewStuff("application/resourcetype", this);
  m_newStuff->uploadResource(fileName);
}

Here createUploadResource() creates the data tarball and returns the name with path to the created tarball.

That is all. I hope you will find this tutorial useful.