Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package gnome-autoar for openSUSE:Factory 
checked in at 2021-04-18 21:45:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gnome-autoar (Old)
 and      /work/SRC/openSUSE:Factory/.gnome-autoar.new.12324 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gnome-autoar"

Sun Apr 18 21:45:02 2021 rev:7 rq:885656 version:0.3.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/gnome-autoar/gnome-autoar.changes        
2021-02-18 20:49:51.475294485 +0100
+++ /work/SRC/openSUSE:Factory/.gnome-autoar.new.12324/gnome-autoar.changes     
2021-04-18 21:45:11.368729862 +0200
@@ -1,0 +2,9 @@
+Wed Apr 14 00:40:44 UTC 2021 - Ferdinand Thiessen <[email protected]>
+
+- Update to version 0.3.1:
+  + Disallow symlinks in parents completely when extracting
+    ( CVE-2021-28650 )
+  + Drop recursive delete on failure to prevent data loss
+  + Add back RAR support
+
+-------------------------------------------------------------------

Old:
----
  gnome-autoar-0.3.0.tar.xz

New:
----
  gnome-autoar-0.3.1.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gnome-autoar.spec ++++++
--- /var/tmp/diff_new_pack.UKvGVp/_old  2021-04-18 21:45:11.732730477 +0200
+++ /var/tmp/diff_new_pack.UKvGVp/_new  2021-04-18 21:45:11.732730477 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           gnome-autoar
-Version:        0.3.0
+Version:        0.3.1
 Release:        0
 Summary:        Automatic archives creating and extracting library
 License:        LGPL-2.0-or-later

++++++ gnome-autoar-0.3.0.tar.xz -> gnome-autoar-0.3.1.tar.xz ++++++
++++ 1615 lines of diff (skipped)
++++    retrying with extended exclude list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/NEWS new/gnome-autoar-0.3.1/NEWS
--- old/gnome-autoar-0.3.0/NEWS 2021-02-12 16:23:27.000000000 +0100
+++ new/gnome-autoar-0.3.1/NEWS 2021-03-13 08:48:12.000000000 +0100
@@ -1,3 +1,9 @@
+Major changes in 0.3.1:
+* Disallow symlinks in parents completely when extracting (Ondrej Holy)
+* Make AutoarExtractor documentation clearer (Ondrej Holy)
+* Drop recursive delete on failure to prevent data loss (Ondrej Holy)
+* Add back RAR support (Matthias)
+
 Major changes in 0.3.0:
 * Recognize MIME type aliases of extractable archives (Hernawan Fa'iz Abdillah)
 * Add extraction support for password-protected archives (Felipe Borges)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/configure.ac new/gnome-autoar-0.3.1/configure.ac
--- old/gnome-autoar-0.3.0/configure.ac 2021-02-12 15:47:26.000000000 +0100
+++ new/gnome-autoar-0.3.1/configure.ac 2021-03-13 08:50:53.000000000 +0100
@@ -6,7 +6,7 @@
 
 m4_define([major_version], [0])
 m4_define([minor_version], [3])
-m4_define([micro_version], [0])
+m4_define([micro_version], [1])
 
 AC_INIT([gnome-autoar],
         [major_version.minor_version.micro_version],
@@ -57,7 +57,7 @@
 # Checks for libraries.
 GLIB_REQUIRED=2.35.6
 GTK_REQUIRED=3.2
-LIBARCHIVE_REQUIRED=3.2.0
+LIBARCHIVE_REQUIRED=3.4.0
 
 PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= $LIBARCHIVE_REQUIRED],
                   [GNOME_AUTOAR_LIBARCHIVE_REQUIRES="libarchive"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/docs/reference/html/AutoarExtractor.html 
new/gnome-autoar-0.3.1/docs/reference/html/AutoarExtractor.html
--- old/gnome-autoar-0.3.0/docs/reference/html/AutoarExtractor.html     
2021-02-12 16:28:02.000000000 +0100
+++ new/gnome-autoar-0.3.1/docs/reference/html/AutoarExtractor.html     
2021-03-13 08:56:08.000000000 +0100
@@ -329,15 +329,15 @@
 <p>The <a class="link" href="AutoarExtractor.html" 
title="AutoarExtractor"><span class="type">AutoarExtractor</span></a> object is 
used to automatically extract files and
 directories from an archive. By default, it will only create one file or
 directory in the output directory. This is done to avoid clutter on the
-user's output directory. If the archive contains only one file, the file
-will be extracted to the output directory. If the archive has more than one
-file, the files will be extracted in a directory having the same name as the
-archive, except the extension. It is also possible to just extract all files
-to the output directory (note that this will not perform any checks) by
-using <a class="link" 
href="AutoarExtractor.html#autoar-extractor-set-output-is-dest" 
title="autoar_extractor_set_output_is_dest??()"><code 
class="function">autoar_extractor_set_output_is_dest()</code></a>.</p>
+user's output directory. If the archive contains only one file with the same
+name as the source archive without the extension, the file will be extracted
+to the output directory. Otherwise the files will be extracted in a directory
+having the same name as the source archive, except the extension. It is also
+possible to just extract all files to the output directory (note that this
+will not perform any checks) by using <a class="link" 
href="AutoarExtractor.html#autoar-extractor-set-output-is-dest" 
title="autoar_extractor_set_output_is_dest??()"><code 
class="function">autoar_extractor_set_output_is_dest()</code></a>.</p>
 <p><a class="link" href="AutoarExtractor.html" title="AutoarExtractor"><span 
class="type">AutoarExtractor</span></a> will not attempt to solve any name 
conflicts. If the
 destination directory already exists, it will proceed normally. If the
-destionation directory cannot be created, it will fail with an error.
+destination directory cannot be created, it will fail with an error.
 It is possible however to change the destination, when
 <a class="link" href="AutoarExtractor.html#AutoarExtractor-decide-destination" 
title="The ???decide-destination??? signal"><span 
class="type">???decide-destination???</span></a> is emitted. The signal 
provides the decided
 destination and the list of files to be extracted. The signal also allows a
@@ -381,14 +381,12 @@
 <tbody>
 <tr>
 <td class="parameter_name"><p>source_file</p></td>
-<td class="parameter_description"><p>source archive</p></td>
+<td class="parameter_description"><p>a <span class="type">GFile</span> for the 
source archive</p></td>
 <td class="parameter_annotations">??</td>
 </tr>
 <tr>
 <td class="parameter_name"><p>output_file</p></td>
-<td class="parameter_description"><p>output directory of extracted file or 
directory, or the
-file name of the extracted file or directory itself if you set
-<a class="link" href="AutoarExtractor.html#AutoarExtractor--output-is-dest" 
title="The ???output-is-dest??? property"><span 
class="type">???output-is-dest???</span></a> on the returned object</p></td>
+<td class="parameter_description"><p>a <span class="type">GFile</span> for the 
directory where the files will be extracted</p></td>
 <td class="parameter_annotations">??</td>
 </tr>
 </tbody>
@@ -498,8 +496,9 @@
 <a 
name="autoar-extractor-get-output-file"></a><h3>autoar_extractor_get_output_file??()</h3>
 <pre class="programlisting"><span class="returnvalue">GFile</span>??*
 autoar_extractor_get_output_file (<em class="parameter"><code><a class="link" 
href="AutoarExtractor.html" title="AutoarExtractor"><span 
class="type">AutoarExtractor</span></a> *self</code></em>);</pre>
-<p>This function is similar to <code 
class="function">autoar_extractor_get_output()</code>, except for the
-return value is a <span class="type">GFile</span>.</p>
+<p>Gets the <span class="type">GFile</span> object which represents the output 
directory of extracted
+file or directory, or the extracted file or directory itself if you set
+<a class="link" href="AutoarExtractor.html#AutoarExtractor--output-is-dest" 
title="The ???output-is-dest??? property"><span 
class="type">???output-is-dest???</span></a> on the returned object.</p>
 <div class="refsect3">
 <a name="autoar-extractor-get-output-file.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" 
border="0">
@@ -649,8 +648,8 @@
 </div>
 <div class="refsect3">
 <a name="autoar-extractor-get-output-is-dest.returns"></a><h4>Returns</h4>
-<p> <code class="literal">TRUE</code> if <span 
class="type">???output???</span> is the location of extracted file
-or directory</p>
+<p> <code class="literal">TRUE</code> if <a class="link" 
href="AutoarExtractor.html#AutoarExtractor--output-file" title="The 
???output-file??? property"><span class="type">???output-file???</span></a> is 
the destination for
+extracted files</p>
 </div>
 </div>
 <hr>
@@ -715,12 +714,13 @@
 autoar_extractor_set_output_is_dest (<em class="parameter"><code><a 
class="link" href="AutoarExtractor.html" title="AutoarExtractor"><span 
class="type">AutoarExtractor</span></a> *self</code></em>,
                                      <em class="parameter"><code><span 
class="type">gboolean</span> output_is_dest</code></em>);</pre>
 <p>By default <a class="link" 
href="AutoarExtractor.html#AutoarExtractor--output-is-dest" title="The 
???output-is-dest??? property"><span 
class="type">???output-is-dest???</span></a> is set to <code 
class="literal">FALSE</code>, which means
-only one file or directory will be generated. The destination is internally
-determined by analyzing the contents of the archive. If this is not wanted,
-<a class="link" href="AutoarExtractor.html#AutoarExtractor--output-is-dest" 
title="The ???output-is-dest??? property"><span 
class="type">???output-is-dest???</span></a> can be set to <code 
class="literal">TRUE</code>, which will make
-<span class="type">???output???</span> the destination for extracted files. In 
any case, the
-destination will be notified via <a class="link" 
href="AutoarExtractor.html#AutoarExtractor-decide-destination" title="The 
???decide-destination??? signal"><span 
class="type">???decide-destination???</span></a>, when
-it is possible to set a new destination.</p>
+only one file or directory will be created in <a class="link" 
href="AutoarExtractor.html#AutoarExtractor--output-file" title="The 
???output-file??? property"><span class="type">???output-file???</span></a>.
+The destination is internally determined by analyzing the contents of the
+archive. If this is not wanted, <a class="link" 
href="AutoarExtractor.html#AutoarExtractor--output-is-dest" title="The 
???output-is-dest??? property"><span 
class="type">???output-is-dest???</span></a> can be set to
+<code class="literal">TRUE</code>, which will make <a class="link" 
href="AutoarExtractor.html#AutoarExtractor--output-file" title="The 
???output-file??? property"><span class="type">???output-file???</span></a> the 
destination for
+extracted files. In any case, the destination will be notified via
+<a class="link" href="AutoarExtractor.html#AutoarExtractor-decide-destination" 
title="The ???decide-destination??? signal"><span 
class="type">???decide-destination???</span></a>, when it is possible to set a 
new
+destination.</p>
 <p><a class="link" href="AutoarExtractor.html" title="AutoarExtractor"><span 
class="type">AutoarExtractor</span></a> will attempt to create the destination 
regardless to whether
 its path was internally decided or not.</p>
 <p>This function should only be called before calling <a class="link" 
href="AutoarExtractor.html#autoar-extractor-start" 
title="autoar_extractor_start??()"><code 
class="function">autoar_extractor_start()</code></a> or
@@ -741,8 +741,8 @@
 </tr>
 <tr>
 <td class="parameter_name"><p>output_is_dest</p></td>
-<td class="parameter_description"><p><code class="literal">TRUE</code> if the 
location of the extracted directory or file
-has been already decided</p></td>
+<td class="parameter_description"><p><code class="literal">TRUE</code> if <a 
class="link" href="AutoarExtractor.html#AutoarExtractor--output-file" 
title="The ???output-file??? property"><span 
class="type">???output-file???</span></a> is the destination for
+extracted files</p></td>
 <td class="parameter_annotations">??</td>
 </tr>
 </tbody>
@@ -842,6 +842,11 @@
 </colgroup>
 <tbody>
 <tr>
+<td class="enum_member_name"><p><a 
name="AUTOAR-CONFLICT-UNHANDLED:CAPS"></a>AUTOAR_CONFLICT_UNHANDLED</p></td>
+<td>??</td>
+<td>??</td>
+</tr>
+<tr>
 <td class="enum_member_name"><p><a 
name="AUTOAR-CONFLICT-SKIP:CAPS"></a>AUTOAR_CONFLICT_SKIP</p></td>
 <td>??</td>
 <td>??</td>
@@ -908,7 +913,7 @@
 <div class="refsect2">
 <a name="AutoarExtractor--output-file"></a><h3>The <code 
class="literal">???output-file???</code> property</h3>
 <pre class="programlisting">  ???output-file???              <span 
class="type">GFile</span>??*</pre>
-<p>Output directory GFile of extracted archives.</p>
+<p>The #GFile of the directory where the files will be extracted.</p>
 <p>Owner: AutoarExtractor</p>
 <p>Flags: Read / Write / Construct??Only</p>
 </div>
@@ -916,7 +921,7 @@
 <div class="refsect2">
 <a name="AutoarExtractor--output-is-dest"></a><h3>The <code 
class="literal">???output-is-dest???</code> property</h3>
 <pre class="programlisting">  ???output-is-dest???           <span 
class="type">gboolean</span></pre>
-<p>Whether output direcotry is used as destination.</p>
+<p>Whether #AutoarExtractor:output-file is used as destination.</p>
 <p>Owner: AutoarExtractor</p>
 <p>Flags: Read / Write / Construct</p>
 <p>Default value: FALSE</p>
@@ -925,7 +930,7 @@
 <div class="refsect2">
 <a name="AutoarExtractor--source-file"></a><h3>The <code 
class="literal">???source-file???</code> property</h3>
 <pre class="programlisting">  ???source-file???              <span 
class="type">GFile</span>??*</pre>
-<p>The archive GFile to be extracted.</p>
+<p>The #GFile of the source archive that will be extracted.</p>
 <p>Owner: AutoarExtractor</p>
 <p>Flags: Read / Write / Construct??Only</p>
 </div>
@@ -1037,12 +1042,13 @@
 </tr>
 <tr>
 <td class="parameter_name"><p>file</p></td>
-<td class="parameter_description"><p>the file that caused a conflict</p></td>
+<td class="parameter_description"><p>a <span class="type">GFile</span> for the 
file that caused a conflict</p></td>
 <td class="parameter_annotations">??</td>
 </tr>
 <tr>
 <td class="parameter_name"><p>new_file</p></td>
-<td class="parameter_description"><p>an address to store the new destination 
for a conflict file</p></td>
+<td class="parameter_description"><p>a <span class="type">GFile</span> for the 
new destination of <em class="parameter"><code>file</code></em>
+</p></td>
 <td class="parameter_annotations">??</td>
 </tr>
 <tr>
@@ -1055,9 +1061,11 @@
 </div>
 <div class="refsect3">
 <a name="AutoarExtractor-conflict.returns"></a><h4>Returns</h4>
-<p> the action to be performed by <a class="link" href="AutoarExtractor.html" 
title="AutoarExtractor"><span class="type">AutoarExtractor</span></a></p>
+<p> the <a class="link" href="AutoarExtractor.html#AutoarConflictAction" 
title="enum AutoarConflictAction"><span 
class="type">AutoarConflictAction</span></a> to be performed by <a class="link" 
href="AutoarExtractor.html" title="AutoarExtractor"><span 
class="type">AutoarExtractor</span></a></p>
 <p>This signal is used to report and offer the possibility to solve name
-conflicts when extracting files.</p>
+conflicts when extracting files. If it is not handled, the <em 
class="parameter"><code>file</code></em>
+will be
+skipped.</p>
 </div>
 <p>Flags: Run Last</p>
 </div>
@@ -1085,14 +1093,14 @@
 </tr>
 <tr>
 <td class="parameter_name"><p>destination</p></td>
-<td class="parameter_description"><p>the location where files will be 
extracted</p></td>
+<td class="parameter_description"><p>a <span class="type">GFile</span> for the 
location where files will be extracted</p></td>
 <td class="parameter_annotations">??</td>
 </tr>
 <tr>
 <td class="parameter_name"><p>files</p></td>
-<td class="parameter_description"><p>the list of files to be extracted. All 
have <em class="parameter"><code>destination</code></em>
-as their
-common prefix</p></td>
+<td class="parameter_description"><p>the list of <span 
class="type">GFile</span> objects to be extracted. All have <em 
class="parameter"><code>destination</code></em>
+as
+their common prefix</p></td>
 <td class="parameter_annotations">??</td>
 </tr>
 <tr>
@@ -1105,8 +1113,9 @@
 </div>
 <div class="refsect3">
 <a name="AutoarExtractor-decide-destination.returns"></a><h4>Returns</h4>
-<p>a new destination that will overwrite the previous
-one, or <code class="literal">NULL</code> if this is not wanted</p>
+<p><span class="type">GFile</span> for location that will overwrite
+<em class="parameter"><code>destination</code></em>
+, or <code class="literal">NULL</code> if this is not wanted</p>
 <p>This signal is emitted when the path of the destination is determined. It is
 useful for solving name conflicts or for setting a new destination, based on
 the contents of the archive. </p>
@@ -1163,7 +1172,7 @@
                <span class="type">guint64</span>          completed_size,
                <span class="type">guint</span>            completed_files,
                <span class="type">gpointer</span>         user_data)</pre>
-<p>This signal is used to report progress of creating archives.</p>
+<p>This signal is used to report progress of extraction.</p>
 <div class="refsect3">
 <a name="AutoarExtractor-progress.parameters"></a><h4>Parameters</h4>
 <div class="informaltable"><table class="informaltable" width="100%" 
border="0">
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/docs/reference/html/gnome-autoar.devhelp2 
new/gnome-autoar-0.3.1/docs/reference/html/gnome-autoar.devhelp2
--- old/gnome-autoar-0.3.0/docs/reference/html/gnome-autoar.devhelp2    
2021-02-12 16:28:02.000000000 +0100
+++ new/gnome-autoar-0.3.1/docs/reference/html/gnome-autoar.devhelp2    
2021-03-13 08:56:08.000000000 +0100
@@ -122,6 +122,7 @@
     <keyword type="function" name="autoar_gtk_chooser_simple_get??()" 
link="gnome-autoar-autoar-gtk-chooser.html#autoar-gtk-chooser-simple-get"/>
     <keyword type="function" name="autoar_gtk_chooser_advanced_new??()" 
link="gnome-autoar-autoar-gtk-chooser.html#autoar-gtk-chooser-advanced-new"/>
     <keyword type="function" name="autoar_gtk_chooser_advanced_get??()" 
link="gnome-autoar-autoar-gtk-chooser.html#autoar-gtk-chooser-advanced-get"/>
+    <keyword type="constant" name="AUTOAR_CONFLICT_UNHANDLED" 
link="AutoarExtractor.html#AUTOAR-CONFLICT-UNHANDLED:CAPS"/>
     <keyword type="constant" name="AUTOAR_CONFLICT_SKIP" 
link="AutoarExtractor.html#AUTOAR-CONFLICT-SKIP:CAPS"/>
     <keyword type="constant" name="AUTOAR_CONFLICT_OVERWRITE" 
link="AutoarExtractor.html#AUTOAR-CONFLICT-OVERWRITE:CAPS"/>
     <keyword type="constant" name="AUTOAR_CONFLICT_CHANGE_DESTINATION" 
link="AutoarExtractor.html#AUTOAR-CONFLICT-CHANGE-DESTINATION:CAPS"/>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/gnome-autoar/autoar-enum-types.c 
new/gnome-autoar-0.3.1/gnome-autoar/autoar-enum-types.c
--- old/gnome-autoar-0.3.0/gnome-autoar/autoar-enum-types.c     2021-02-12 
10:46:16.000000000 +0100
+++ new/gnome-autoar-0.3.1/gnome-autoar/autoar-enum-types.c     2021-03-13 
08:52:39.000000000 +0100
@@ -11,6 +11,9 @@
   if (G_UNLIKELY (!type))
   {
     static const GEnumValue values[] = {
+      { AUTOAR_CONFLICT_UNHANDLED,
+        "AUTOAR_CONFLICT_UNHANDLED",
+        "unhandled" },
       { AUTOAR_CONFLICT_SKIP,
         "AUTOAR_CONFLICT_SKIP",
         "skip" },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/gnome-autoar/autoar-extractor.c 
new/gnome-autoar-0.3.1/gnome-autoar/autoar-extractor.c
--- old/gnome-autoar-0.3.0/gnome-autoar/autoar-extractor.c      2021-02-12 
15:45:53.000000000 +0100
+++ new/gnome-autoar-0.3.1/gnome-autoar/autoar-extractor.c      2021-03-12 
16:46:50.000000000 +0100
@@ -60,16 +60,16 @@
  * The #AutoarExtractor object is used to automatically extract files and
  * directories from an archive. By default, it will only create one file or
  * directory in the output directory. This is done to avoid clutter on the
- * user's output directory. If the archive contains only one file, the file
- * will be extracted to the output directory. If the archive has more than one
- * file, the files will be extracted in a directory having the same name as the
- * archive, except the extension. It is also possible to just extract all files
- * to the output directory (note that this will not perform any checks) by
- * using autoar_extractor_set_output_is_dest().
+ * user's output directory. If the archive contains only one file with the same
+ * name as the source archive without the extension, the file will be extracted
+ * to the output directory. Otherwise the files will be extracted in a 
directory
+ * having the same name as the source archive, except the extension. It is also
+ * possible to just extract all files to the output directory (note that this
+ * will not perform any checks) by using autoar_extractor_set_output_is_dest().
 
  * #AutoarExtractor will not attempt to solve any name conflicts. If the
  * destination directory already exists, it will proceed normally. If the
- * destionation directory cannot be created, it will fail with an error.
+ * destination directory cannot be created, it will fail with an error.
  * It is possible however to change the destination, when
  * #AutoarExtractor::decide-destination is emitted. The signal provides the 
decided
  * destination and the list of files to be extracted. The signal also allows a
@@ -289,8 +289,9 @@
  * autoar_extractor_get_output_file:
  * @self: an #AutoarExtractor
  *
- * This function is similar to autoar_extractor_get_output(), except for the
- * return value is a #GFile.
+ * Gets the #GFile object which represents the output directory of extracted
+ * file or directory, or the extracted file or directory itself if you set
+ * #AutoarExtractor:output-is-dest on the returned object.
  *
  * Returns: (transfer none): a #GFile
  **/
@@ -368,8 +369,8 @@
  *
  * See autoar_extractor_set_output_is_dest().
  *
- * Returns: %TRUE if #AutoarExtractor:output is the location of extracted file
- * or directory
+ * Returns: %TRUE if #AutoarExtractor:output-file is the destination for
+ * extracted files
  **/
 gboolean
 autoar_extractor_get_output_is_dest (AutoarExtractor *self)
@@ -413,16 +414,17 @@
 /**
  * autoar_extractor_set_output_is_dest:
  * @self: an #AutoarExtractor
- * @output_is_dest: %TRUE if the location of the extracted directory or file
- * has been already decided
+ * @output_is_dest: %TRUE if #AutoarExtractor:output-file is the destination 
for
+ * extracted files
  *
  * By default #AutoarExtractor:output-is-dest is set to %FALSE, which means
- * only one file or directory will be generated. The destination is internally
- * determined by analyzing the contents of the archive. If this is not wanted,
- * #AutoarExtractor:output-is-dest can be set to %TRUE, which will make
- * #AutoarExtractor:output the destination for extracted files. In any case, 
the
- * destination will be notified via #AutoarExtractor::decide-destination, when
- * it is possible to set a new destination.
+ * only one file or directory will be created in #AutoarExtractor:output-file.
+ * The destination is internally determined by analyzing the contents of the
+ * archive. If this is not wanted, #AutoarExtractor:output-is-dest can be set 
to
+ * %TRUE, which will make #AutoarExtractor:output-file the destination for
+ * extracted files. In any case, the destination will be notified via
+ * #AutoarExtractor::decide-destination, when it is possible to set a new
+ * destination.
  *
  * #AutoarExtractor will attempt to create the destination regardless to 
whether
  * its path was internally decided or not.
@@ -778,13 +780,15 @@
                                   GFile            *file,
                                   GFile           **new_file)
 {
-  AutoarConflictAction action = AUTOAR_CONFLICT_OVERWRITE;
+  AutoarConflictAction action = AUTOAR_CONFLICT_UNHANDLED;
 
   autoar_common_g_signal_emit (self, self->in_thread,
                                autoar_extractor_signals[CONFLICT], 0,
                                file,
                                new_file,
                                &action);
+  if (action == AUTOAR_CONFLICT_UNHANDLED)
+    return AUTOAR_CONFLICT_SKIP;
 
   if (*new_file) {
     g_autofree char *previous_path;
@@ -868,70 +872,35 @@
   return prefix;
 }
 
-static gboolean
-is_valid_filename (GFile *file, GFile *destination)
-{
-  g_autoptr (GFile) parent = NULL;
-  g_autoptr (GFileInfo) info = NULL;
-  g_autoptr (GError) error = NULL;
-
-  if (g_file_equal (file, destination))
-    return TRUE;
-
-  if (!g_file_has_prefix (file, destination))
-    return FALSE;
-
-  /* Resolve symbolic link ancestors to confirm file is actually inside 
destination. */
-  parent = g_file_get_parent (file);
-  info = g_file_query_info (parent,
-                            G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
-                            G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
-                            G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                            NULL,
-                            &error);
-
-  /* The parent directories don't have to be created yet. */
-  if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
-    return FALSE;
-
-  if (info && g_file_info_get_is_symlink (info)) {
-    g_autoptr (GFile) cwd = NULL;
-    const gchar *target;
-
-    target = g_file_info_get_symlink_target (info);
-    if (g_path_is_absolute (target))
-      return FALSE;
-
-    cwd = g_file_get_parent (parent);
-    g_object_unref (parent);
-    parent = g_file_resolve_relative_path (cwd, target);
-  }
-
-  /* Climb up the path to resolve every symbolic link ancestor found */
-  return is_valid_filename (parent, destination);
-}
-
 static GFile*
 autoar_extractor_do_sanitize_pathname (AutoarExtractor *self,
                                        const char      *pathname_bytes)
 {
   GFile *extracted_filename;
   gboolean valid_filename;
-  g_autofree char *sanitized_pathname = NULL;
+  g_autofree char *sanitized_pathname;
   g_autofree char *utf8_pathname;
+  GFile *destination;
+
+  /* Use output_file when called from autoar_extractor_step_scan_toplevel(). */
+  destination = (self->destination_dir != NULL) ? self->destination_dir : 
self->output_file;
 
   utf8_pathname = autoar_common_get_utf8_pathname (pathname_bytes);
-  extracted_filename = g_file_get_child (self->destination_dir,
+  extracted_filename = g_file_get_child (destination,
                                          utf8_pathname ?  utf8_pathname : 
pathname_bytes);
 
-  valid_filename = is_valid_filename (extracted_filename, 
self->destination_dir);
+  valid_filename =
+    g_file_equal (extracted_filename, destination) ||
+    g_file_has_prefix (extracted_filename, destination);
+
   if (!valid_filename) {
-    g_warning ("autoar_extractor_do_sanitize_pathname: %s is outside of the 
destination dir",
-                g_file_peek_path (extracted_filename));
+    g_autofree char *basename;
+
+    basename = g_file_get_basename (extracted_filename);
 
     g_object_unref (extracted_filename);
 
-    return NULL;
+    extracted_filename = g_file_get_child (destination, basename);
   }
 
   if (self->prefix != NULL && self->new_prefix != NULL) {
@@ -955,92 +924,42 @@
   return extracted_filename;
 }
 
-static gboolean
-autoar_extractor_check_file_conflict (GFile  *file,
+/* The function checks @file for conflicts with already existing files on the
+ * disk. It also recursively checks parents of @file to be sure it is 
directory.
+ * It doesn't follow symlinks, so symlinks in parents are also considered as
+ * conflicts even though they point to directory. It returns #GFile object for
+ * the file, which cause the conflict (so @file, or some of its parents). If
+ * there aren't any conflicts, NULL is returned.
+ */
+static GFile *
+autoar_extractor_check_file_conflict (AutoarExtractor *self,
+                                      GFile  *file,
                                       mode_t  extracted_filetype)
 {
   GFileType file_type;
-  gboolean conflict = FALSE;
+  g_autoptr (GFile) parent = NULL;
 
   file_type = g_file_query_file_type (file,
-                                      G_FILE_QUERY_INFO_NONE,
+                                      G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                       NULL);
-  /* If there is no file with the given name, there will be no conflict */
-  if (file_type == G_FILE_TYPE_UNKNOWN) {
-    return FALSE;
-  }
 
-  switch (extracted_filetype) {
-    case AE_IFDIR:
-      break;
-    case AE_IFREG:
-    case AE_IFLNK:
-#if defined HAVE_MKFIFO || defined HAVE_MKNOD
-    case AE_IFIFO:
-#endif
-#ifdef HAVE_MKNOD
-    case AE_IFSOCK:
-    case AE_IFBLK:
-    case AE_IFCHR:
-#endif
-      conflict = TRUE;
-      break;
-    default:
-      break;
+  /* It is a conflict if the file already exists with an exception for already
+   * existing directories.
+   */
+  if (file_type != G_FILE_TYPE_UNKNOWN &&
+      (file_type != G_FILE_TYPE_DIRECTORY ||
+       extracted_filetype != AE_IFDIR)) {
+    return g_object_ref (file);
   }
 
-  return conflict;
-}
-
-static gboolean
-autoar_extractor_delete_file_recursively (AutoarExtractor *self,
-                                          GFile *file)
-{
-  gboolean success;
-  g_autoptr (GError) error = NULL;
-
-  do {
-    g_autoptr (GFileEnumerator) enumerator = NULL;
-
-    success = g_file_delete (file, self->cancellable, &error);
-    if (success || !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY)) 
{
-      break;
-    }
-
-    g_clear_error (&error);
-    enumerator = g_file_enumerate_children (file,
-                                            G_FILE_ATTRIBUTE_STANDARD_NAME,
-                                            G_FILE_QUERY_INFO_NONE,
-                                            self->cancellable, &error);
-    if (enumerator) {
-      GFileInfo *info;
-
-      success = TRUE;
-
-      info = g_file_enumerator_next_file (enumerator,
-                                          self->cancellable,
-                                          &error);
-      while (info != NULL) {
-        g_autoptr (GFile) child = NULL;
-
-        child = g_file_enumerator_get_child (enumerator, info);
-
-        success = success && autoar_extractor_delete_file_recursively (self, 
child);
-        g_object_unref (info);
-
-        info = g_file_enumerator_next_file (enumerator,
-                                            self->cancellable,
-                                            &error);
-      }
-    }
-
-    if (error != NULL) {
-      success = FALSE;
-    }
-
-  } while (success);
+  if ((self->new_prefix && g_file_equal (self->new_prefix, file)) ||
+      (!self->new_prefix && g_file_equal (self->destination_dir, file))) {
+    return NULL;
+  }
 
-  return success;
+  /* Check also parents for conflict to be sure it is directory. */
+  parent = g_file_get_parent (file);
+  return autoar_extractor_check_file_conflict (self, parent, AE_IFDIR);
 }
 
 static void
@@ -1199,12 +1118,10 @@
 
         g_debug ("autoar_extractor_do_write_entry: case REG");
 
-        ostream = (GOutputStream*)g_file_replace (dest,
-                                                  NULL,
-                                                  FALSE,
-                                                  G_FILE_CREATE_NONE,
-                                                  self->cancellable,
-                                                  &(self->error));
+        ostream = (GOutputStream*)g_file_create (dest,
+                                                 G_FILE_CREATE_NONE,
+                                                 self->cancellable,
+                                                 &(self->error));
         if (self->error != NULL) {
           g_object_unref (info);
           return;
@@ -1242,7 +1159,6 @@
             }
 
             if (r == ARCHIVE_FAILED) {
-              autoar_extractor_delete_file_recursively (self, 
self->destination_dir);
               if (self->error == NULL) {
                 self->error = g_error_new (AUTOAR_EXTRACTOR_ERROR,
                                            INCORRECT_PASSPHRASE_ERRNO,
@@ -1293,11 +1209,17 @@
       }
       break;
     case AE_IFLNK:
-      g_debug ("autoar_extractor_do_write_entry: case LNK");
-      g_file_make_symbolic_link (dest,
-                                 archive_entry_symlink (entry),
-                                 self->cancellable,
-                                 &(self->error));
+      {
+        const char *symlink_path = archive_entry_symlink (entry);
+
+        g_debug ("autoar_extractor_do_write_entry: case LNK, %s => %s",
+                 g_file_peek_path (dest), symlink_path);
+
+        g_file_make_symbolic_link (dest,
+                                   symlink_path,
+                                   self->cancellable,
+                                   &(self->error));
+      }
       break;
     /* FIFOs, sockets, block files, character files are not important
      * in the regular archives, so errors are not fatal. */
@@ -1401,8 +1323,8 @@
 
   g_object_class_install_property (object_class, PROP_SOURCE_FILE,
                                    g_param_spec_object ("source-file",
-                                                        "Source archive GFile",
-                                                        "The archive GFile to 
be extracted",
+                                                        "Source archive",
+                                                        "The #GFile of the 
source archive that will be extracted",
                                                         G_TYPE_FILE,
                                                         G_PARAM_READWRITE |
                                                         G_PARAM_CONSTRUCT_ONLY 
|
@@ -1410,8 +1332,8 @@
 
   g_object_class_install_property (object_class, PROP_OUTPUT_FILE,
                                    g_param_spec_object ("output-file",
-                                                        "Output directory 
GFile",
-                                                        "Output directory 
GFile of extracted archives",
+                                                        "Output file",
+                                                        "The #GFile of the 
directory where the files will be extracted",
                                                         G_TYPE_FILE,
                                                         G_PARAM_READWRITE |
                                                         G_PARAM_CONSTRUCT_ONLY 
|
@@ -1452,7 +1374,7 @@
   g_object_class_install_property (object_class, PROP_OUTPUT_IS_DEST,
                                    g_param_spec_boolean ("output-is-dest",
                                                          "Output is 
destination",
-                                                         "Whether output 
direcotry is used as destination",
+                                                         "Whether 
#AutoarExtractor:output-file is used as destination",
                                                          FALSE,
                                                          G_PARAM_READWRITE |
                                                          G_PARAM_CONSTRUCT |
@@ -1498,12 +1420,12 @@
 /**
  * AutoarExtractor::decide-destination:
  * @self: the #AutoarExtractor
- * @destination: the location where files will be extracted
- * @files: the list of files to be extracted. All have @destination as their
-           common prefix
+ * @destination: a #GFile for the location where files will be extracted
+ * @files: the list of #GFile objects to be extracted. All have @destination as
+ *         their common prefix
  *
- * Returns: (transfer full): a new destination that will overwrite the previous
- *                           one, or %NULL if this is not wanted
+ * Returns: (transfer full): #GFile for location that will overwrite
+ *                           @destination, or %NULL if this is not wanted
  *
  * This signal is emitted when the path of the destination is determined. It is
  * useful for solving name conflicts or for setting a new destination, based on
@@ -1526,7 +1448,7 @@
  * @completed_size: bytes has been written to disk
  * @completed_files: number of files have been written to disk
  *
- * This signal is used to report progress of creating archives.
+ * This signal is used to report progress of extraction.
  **/
   autoar_extractor_signals[PROGRESS] =
     g_signal_new ("progress",
@@ -1542,13 +1464,14 @@
 /**
  * AutoarExtractor::conflict:
  * @self: the #AutoarExtractor
- * @file: the file that caused a conflict
- * @new_file: an address to store the new destination for a conflict file
+ * @file: a #GFile for the file that caused a conflict
+ * @new_file: a #GFile for the new destination of @file
  *
- * Returns: the action to be performed by #AutoarExtractor
+ * Returns: the #AutoarConflictAction to be performed by #AutoarExtractor
  *
  * This signal is used to report and offer the possibility to solve name
- * conflicts when extracting files.
+ * conflicts when extracting files. If it is not handled, the @file will be
+ * skipped.
  **/
   autoar_extractor_signals[CONFLICT] =
     g_signal_new ("conflict",
@@ -1669,10 +1592,8 @@
 
 /**
  * autoar_extractor_new:
- * @source_file: source archive
- * @output_file: output directory of extracted file or directory, or the
- * file name of the extracted file or directory itself if you set
- * #AutoarExtractor:output-is-dest on the returned object
+ * @source_file: a #GFile for the source archive
+ * @output_file: a #GFile for the directory where the files will be extracted
  *
  * Create a new #AutoarExtractor object.
  *
@@ -1750,22 +1671,31 @@
     }
 
     if (self->use_raw_format) {
-      pathname = autoar_common_get_basename_remove_extension 
(g_file_get_path(self->source_file));
+      pathname = autoar_common_get_basename_remove_extension (g_file_peek_path 
(self->source_file));
       g_debug ("autoar_extractor_step_scan_toplevel: %d: raw pathname = %s",
                self->total_files, pathname);
     } else {
+      const char *symlink_pathname;
+      const char *hardlink_pathname;
+
       pathname = archive_entry_pathname (entry);
       utf8_pathname = autoar_common_get_utf8_pathname (pathname);
+      symlink_pathname = archive_entry_symlink (entry);
+      hardlink_pathname = archive_entry_hardlink (entry);
 
-      g_debug ("autoar_extractor_step_scan_toplevel: %d: pathname = %s %s%s",
+      g_debug ("autoar_extractor_step_scan_toplevel: %d: pathname = 
%s%s%s%s%s%s%s",
                self->total_files, pathname,
-               utf8_pathname ? "utf8 pathname = " :"",
-               utf8_pathname ? utf8_pathname : "");
+               utf8_pathname ? " utf8 pathname = " : "",
+               utf8_pathname ? utf8_pathname : "",
+               symlink_pathname ? " symlink = " : "",
+               symlink_pathname ? symlink_pathname : "",
+               hardlink_pathname ? " hardlink = " : "",
+               hardlink_pathname ? hardlink_pathname : "");
     }
     self->files_list =
       g_list_prepend (self->files_list,
-                      g_file_get_child (self->output_file,
-                                        utf8_pathname ? utf8_pathname : 
pathname));
+                      autoar_extractor_do_sanitize_pathname (self,
+                                                             utf8_pathname ? 
utf8_pathname : pathname));
     self->total_files++;
     self->total_size += archive_entry_size (entry);
     archive_read_data_skip (a);
@@ -1804,18 +1734,6 @@
 
   self->files_list = g_list_reverse (self->files_list);
 
-  self->prefix =
-    autoar_extractor_get_common_prefix (self->files_list,
-                                        self->output_file);
-
-  if (self->prefix != NULL) {
-    g_autofree char *path_prefix;
-
-    path_prefix = g_file_get_path (self->prefix);
-    g_debug ("autoar_extractor_step_scan_toplevel: pathname_prefix = %s",
-             path_prefix);
-  }
-
   autoar_extractor_signal_scanned (self);
 }
 
@@ -1831,6 +1749,8 @@
     return;
   }
 
+  self->prefix = autoar_extractor_get_common_prefix (self->files_list,
+                                                     self->output_file);
   if (self->prefix != NULL) {
     /* We must check if the archive and the prefix have the same name (without
      * the extension). If they do, then the destination should be the output
@@ -1839,6 +1759,9 @@
     g_autofree char *prefix_name;
     g_autofree char *prefix_name_no_ext;
 
+    g_debug ("autoar_extractor_step_set_destination: pathname_prefix = %s",
+             g_file_peek_path (self->prefix));
+
     prefix_name = g_file_get_basename (self->prefix);
     prefix_name_no_ext = autoar_common_get_basename_remove_extension 
(prefix_name);
 
@@ -1905,19 +1828,18 @@
     }
   }
 
-  destination_name = g_file_get_path (self->new_prefix != NULL ?
-                                      self->new_prefix :
-                                      self->destination_dir);
+  new_destination = (self->new_prefix != NULL) ? self->new_prefix : 
self->destination_dir;
+  destination_name = g_file_get_path (new_destination);
   g_debug ("autoar_extractor_step_decide_destination: destination %s", 
destination_name);
 
-  g_file_make_directory_with_parents (self->destination_dir,
+  g_file_make_directory_with_parents (new_destination,
                                       self->cancellable,
                                       &(self->error));
 
   if (g_error_matches (self->error, G_IO_ERROR, G_IO_ERROR_EXISTS)) {
     GFileType file_type;
 
-    file_type = g_file_query_file_type (self->destination_dir,
+    file_type = g_file_query_file_type (new_destination,
                                         G_FILE_QUERY_INFO_NONE,
                                         NULL);
 
@@ -1960,7 +1882,7 @@
     g_autoptr (GFile) extracted_filename = NULL;
     g_autoptr (GFile) hardlink_filename = NULL;
     AutoarConflictAction action;
-    gboolean file_conflict;
+    g_autoptr (GFile) file_conflict = NULL;
 
     if (g_cancellable_is_cancelled (self->cancellable)) {
       archive_read_free (a);
@@ -1972,34 +1894,53 @@
 
     extracted_filename =
       autoar_extractor_do_sanitize_pathname (self, pathname);
-    if (extracted_filename == NULL) {
-      archive_read_data_skip (a);
-      continue;
-    }
 
     if (hardlink != NULL) {
       hardlink_filename =
         autoar_extractor_do_sanitize_pathname (self, hardlink);
-        if (hardlink_filename == NULL) {
-          archive_read_data_skip (a);
-          continue;
-        }
     }
 
     /* Attempt to solve any name conflict before doing any operations */
-    file_conflict = autoar_extractor_check_file_conflict (extracted_filename,
+    file_conflict = autoar_extractor_check_file_conflict (self,
+                                                          extracted_filename,
                                                           
archive_entry_filetype (entry));
     while (file_conflict) {
       GFile *new_extracted_filename = NULL;
 
+      /* Do not try to solve any conflicts in parents for now. Especially
+       * symlinks in parents are dangerous as it can easily happen that files
+       * are written outside of the destination. The tar cmd fails to extract
+       * such archives with ENOTDIR. Let's do the same here. This is most
+       * probably malicious, or corrupted archive if the conflict was caused
+       * only by files from the archive...
+       */
+      if (!g_file_equal (file_conflict, extracted_filename)) {
+        self->error = g_error_new (G_IO_ERROR,
+                                   G_IO_ERROR_NOT_DIRECTORY,
+                                   "The file is not a directory");
+        archive_read_free (a);
+        return;
+      }
+
       action = autoar_extractor_signal_conflict (self,
                                                  extracted_filename,
                                                  &new_extracted_filename);
 
       switch (action) {
         case AUTOAR_CONFLICT_OVERWRITE:
+          /* It is expected that this will fail for non-empty directories to
+           * prevent data loss.
+           */
+          g_file_delete (extracted_filename, self->cancellable, &self->error);
+          if (self->error != NULL) {
+            archive_read_free (a);
+            return;
+          }
           break;
         case AUTOAR_CONFLICT_CHANGE_DESTINATION:
+          /* FIXME: If the destination is changed for directory, it should be
+           * changed also for its children...
+           */
           g_assert_nonnull (new_extracted_filename);
           g_clear_object (&extracted_filename);
           extracted_filename = new_extracted_filename;
@@ -2016,11 +1957,15 @@
         break;
       }
 
-      file_conflict = autoar_extractor_check_file_conflict (extracted_filename,
+      g_clear_object (&file_conflict);
+      file_conflict = autoar_extractor_check_file_conflict (self,
+                                                            extracted_filename,
                                                             
archive_entry_filetype (entry));
     }
 
     if (file_conflict && action == AUTOAR_CONFLICT_SKIP) {
+      self->total_files -= 1;
+      self->total_size -= archive_entry_size (entry);
       continue;
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/gnome-autoar/autoar-extractor.h 
new/gnome-autoar-0.3.1/gnome-autoar/autoar-extractor.h
--- old/gnome-autoar-0.3.0/gnome-autoar/autoar-extractor.h      2021-02-12 
09:58:12.000000000 +0100
+++ new/gnome-autoar-0.3.1/gnome-autoar/autoar-extractor.h      2021-03-12 
16:46:50.000000000 +0100
@@ -72,7 +72,8 @@
                                                                gint64          
 notify_interval);
 
 typedef enum {
-    AUTOAR_CONFLICT_SKIP = 0,
+    AUTOAR_CONFLICT_UNHANDLED = 0,
+    AUTOAR_CONFLICT_SKIP,
     AUTOAR_CONFLICT_OVERWRITE,
     AUTOAR_CONFLICT_CHANGE_DESTINATION
 } AutoarConflictAction;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/gnome-autoar/autoar-mime-types.c 
new/gnome-autoar-0.3.1/gnome-autoar/autoar-mime-types.c
--- old/gnome-autoar-0.3.0/gnome-autoar/autoar-mime-types.c     2021-02-12 
09:58:12.000000000 +0100
+++ new/gnome-autoar-0.3.1/gnome-autoar/autoar-mime-types.c     2021-03-12 
15:32:52.000000000 +0100
@@ -44,6 +44,7 @@
   "application/zip",
   "application/gzip",
   "application/bzip2",
+  "application/vnd.rar",
   NULL
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/gnome-autoar-0.3.0/tests/test-extract-unit.c 
new/gnome-autoar-0.3.1/tests/test-extract-unit.c
--- old/gnome-autoar-0.3.0/tests/test-extract-unit.c    2020-11-13 
11:53:53.000000000 +0100
+++ new/gnome-autoar-0.3.1/tests/test-extract-unit.c    2021-03-12 
16:46:50.000000000 +0100
@@ -198,7 +198,7 @@
                   gpointer user_data)
 {
   ExtractTestData *data = user_data;
-  AutoarConflictAction action = AUTOAR_CONFLICT_SKIP;
+  AutoarConflictAction action = AUTOAR_CONFLICT_UNHANDLED;
   gpointer value;
   gboolean key_found;
 
@@ -393,7 +393,8 @@
     if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) {
       enumerator = g_file_enumerate_children (file,
                                               G_FILE_ATTRIBUTE_STANDARD_NAME","
-                                              G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                                              G_FILE_ATTRIBUTE_STANDARD_TYPE","
+                                              G_FILE_ATTRIBUTE_STANDARD_SIZE,
                                               
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                               NULL, NULL);
 
@@ -459,7 +460,9 @@
     g_assert_cmpuint (g_file_info_get_file_type (scanned_file_info),
                       ==,
                       g_file_info_get_file_type (corresponding_file_info));
-
+    g_assert_cmpuint (g_file_info_get_size (scanned_file_info),
+                      ==,
+                      g_file_info_get_size (corresponding_file_info));
     g_hash_table_remove (extract_test->unmatched_files, relative_path);
   }
 }
@@ -556,6 +559,49 @@
   assert_reference_and_output_match (extract_test);
 }
 
+/* Be sure that extra folder is not created in case of output-is-dest. */
+static void
+test_one_file_different_name_output_is_dest (void)
+{
+  /* arextract.zip
+   * ????????? arextractdifferent.txt
+   *
+   * 0 directories, 1 file
+   *
+   *
+   * ref
+   * ????????? arextractdifferent.txt
+   *
+   * 0 directory, 1 file
+   */
+
+  g_autoptr (ExtractTest) extract_test = NULL;
+  g_autoptr (ExtractTestData) data = NULL;
+  g_autoptr (GFile) archive = NULL;
+  g_autoptr (AutoarExtractor) extractor = NULL;
+
+  extract_test = extract_test_new 
("test-one-file-different-name-output-is-dest");
+
+  if (!extract_test) {
+    g_assert_nonnull (extract_test);
+    return;
+  }
+
+  archive = g_file_get_child (extract_test->input, "arextract.zip");
+
+  extractor = autoar_extractor_new (archive, extract_test->output);
+  autoar_extractor_set_output_is_dest (extractor, TRUE);
+
+  data = extract_test_data_new_for_extract (extractor);
+
+  autoar_extractor_start (extractor, data->cancellable);
+
+  g_assert_cmpuint (data->number_of_files, ==, 1);
+  g_assert_no_error (data->error);
+  g_assert_true (data->completed_signalled);
+  assert_reference_and_output_match (extract_test);
+}
+
 static void
 test_multiple_files_same_name (void)
 {
@@ -654,7 +700,7 @@
 }
 
 static void
-test_one_file_conflict_overwrite (void)
+test_conflict_overwrite (void)
 {
   /* arextract.zip
    * ????????? arextract.txt
@@ -675,7 +721,7 @@
   g_autoptr (GFile) reference_file = NULL;
   g_autoptr (AutoarExtractor) extractor = NULL;
 
-  extract_test = extract_test_new ("test-one-file-conflict-overwrite");
+  extract_test = extract_test_new ("test-conflict-overwrite");
 
   if (!extract_test) {
     g_assert_nonnull (extract_test);
@@ -687,8 +733,8 @@
   conflict_file = g_file_get_child (extract_test->output,
                                     "arextract.txt");
 
-  g_file_copy (reference_file, conflict_file, G_FILE_COPY_NONE,
-               NULL, NULL, NULL, NULL);
+  g_file_replace_contents (conflict_file, "this file should be overwritten", 
31,
+                           NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL);
 
   archive = g_file_get_child (extract_test->input, "arextract.zip");
 
@@ -696,6 +742,10 @@
 
   data = extract_test_data_new_for_extract (extractor);
 
+  g_hash_table_insert (data->conflict_files_actions,
+                       g_object_ref (conflict_file),
+                       GUINT_TO_POINTER (AUTOAR_CONFLICT_OVERWRITE));
+
   autoar_extractor_start (extractor, data->cancellable);
 
   g_assert_cmpuint (data->number_of_files, ==, 1);
@@ -706,8 +756,173 @@
   assert_reference_and_output_match (extract_test);
 }
 
+/* Be sure that nonempty directories are not replaced to prevent data-loss. */
+static void
+test_conflict_overwrite_nonempty_directory (void)
+{
+  /* arextract.zip
+   * ????????? arextract
+   *
+   * 0 directories, 1 file
+   *
+   *
+   * ref
+   * ????????? arextract
+   *     ????????? dummy
+   *
+   * 1 directory, 1 files
+   */
+
+  g_autoptr (ExtractTest) extract_test = NULL;
+  g_autoptr (ExtractTestData) data = NULL;
+  g_autoptr (GFile) archive = NULL;
+  g_autoptr (GFile) conflict_directory = NULL;
+  g_autoptr (GFile) dummy_file = NULL;
+  g_autoptr (GFileOutputStream) out = NULL;
+  g_autoptr (AutoarExtractor) extractor = NULL;
+
+  extract_test = extract_test_new 
("test-conflict-overwrite-nonempty-directory");
+
+  if (!extract_test) {
+    g_assert_nonnull (extract_test);
+    return;
+  }
+
+  conflict_directory = g_file_get_child (extract_test->output,
+                                         "arextract");
+  dummy_file = g_file_get_child (conflict_directory, "dummy");
+
+  g_file_make_directory (conflict_directory, NULL, NULL);
+
+  out = g_file_create (dummy_file, G_FILE_CREATE_NONE, NULL, NULL);
+  g_output_stream_close (G_OUTPUT_STREAM (out), NULL, NULL);
+
+  archive = g_file_get_child (extract_test->input, "arextract.zip");
+
+  extractor = autoar_extractor_new (archive, extract_test->output);
+
+  data = extract_test_data_new_for_extract (extractor);
+
+  g_hash_table_insert (data->conflict_files_actions,
+                       g_object_ref (conflict_directory),
+                       GUINT_TO_POINTER (AUTOAR_CONFLICT_OVERWRITE));
+
+  autoar_extractor_start (extractor, data->cancellable);
+
+  g_assert_cmpuint (data->number_of_files, ==, 1);
+  g_assert_true (g_hash_table_contains (data->conflict_files,
+                                        conflict_directory));
+  g_assert_error (data->error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY);
+  g_assert_false (data->completed_signalled);
+  assert_reference_and_output_match (extract_test);
+}
+
+/* Be sure that symlink itself is replaced, not its target. */
+static void
+test_conflict_overwrite_symlink (void)
+{
+  /* arextract.tar
+   * ????????? arextract -> arectract.txt
+   * ????????? arextract
+   *
+   * 0 directories, 2 files
+   *
+   *
+   * ref
+   * ????????? arextract
+   *
+   * 0 directories, 1 file
+   */
+
+  g_autoptr (ExtractTest) extract_test = NULL;
+  g_autoptr (ExtractTestData) data = NULL;
+  g_autoptr (GFile) archive = NULL;
+  g_autoptr (GFile) conflict_directory = NULL;
+  g_autoptr (GFile) conflict_file = NULL;
+  g_autoptr (AutoarExtractor) extractor = NULL;
+
+  extract_test = extract_test_new ("test-conflict-overwrite-symlink");
+
+  if (!extract_test) {
+    g_assert_nonnull (extract_test);
+    return;
+  }
+
+  conflict_file = g_file_get_child (extract_test->output, "arextract");
+  archive = g_file_get_child (extract_test->input, "arextract.tar");
+
+  extractor = autoar_extractor_new (archive, extract_test->output);
+
+  data = extract_test_data_new_for_extract (extractor);
+
+  g_hash_table_insert (data->conflict_files_actions,
+                       g_object_ref (conflict_file),
+                       GUINT_TO_POINTER (AUTOAR_CONFLICT_OVERWRITE));
+
+  autoar_extractor_start (extractor, data->cancellable);
+
+  g_assert_cmpuint (data->number_of_files, ==, 2);
+  g_assert_true (g_hash_table_contains (data->conflict_files,
+                                        conflict_file));
+  g_assert_true (data->completed_signalled);
+  assert_reference_and_output_match (extract_test);
+}
+
+/* Be sure that hardlink itself is replaced, not its target. */
+static void
+test_conflict_overwrite_hardlink (void)
+{
+  /* arextract.tar
+   * ????????? arectract.txt
+   * ????????? arextract -> arectract.txt
+   * ????????? arextract
+   *
+   * 0 directories, 3 files
+   *
+   *
+   * ref
+   * ????????? arextract.txt
+   * ????????? arextract
+   *
+   * 0 directories, 2 files
+   */
+
+  g_autoptr (ExtractTest) extract_test = NULL;
+  g_autoptr (ExtractTestData) data = NULL;
+  g_autoptr (GFile) archive = NULL;
+  g_autoptr (GFile) conflict_file = NULL;
+  g_autoptr (AutoarExtractor) extractor = NULL;
+
+  extract_test = extract_test_new ("test-conflict-overwrite-hardlink");
+
+  if (!extract_test) {
+    g_assert_nonnull (extract_test);
+    return;
+  }
+
+  conflict_file = g_file_get_child (extract_test->output, "arextract");
+  archive = g_file_get_child (extract_test->input, "arextract.tar");
+
+  extractor = autoar_extractor_new (archive, extract_test->output);
+  autoar_extractor_set_output_is_dest (extractor, TRUE);
+
+  data = extract_test_data_new_for_extract (extractor);
+
+  g_hash_table_insert (data->conflict_files_actions,
+                       g_object_ref (conflict_file),
+                       GUINT_TO_POINTER (AUTOAR_CONFLICT_OVERWRITE));
+
+  autoar_extractor_start (extractor, data->cancellable);
+
+  g_assert_cmpuint (data->number_of_files, ==, 3);
+  g_assert_true (g_hash_table_contains (data->conflict_files,
+                                        conflict_file));
+  g_assert_true (data->completed_signalled);
+  assert_reference_and_output_match (extract_test);
+}
+
 static void
-test_one_file_conflict_new_destination (void)
+test_conflict_new_destination (void)
 {
   /* arextract.zip
    * ????????? arextract.txt
@@ -729,7 +944,7 @@
   g_autoptr (GFile) reference_file = NULL;
   g_autoptr (AutoarExtractor) extractor = NULL;
 
-  extract_test = extract_test_new ("test-one-file-conflict-new-destination");
+  extract_test = extract_test_new ("test-conflict-new-destination");
 
   if (!extract_test) {
     g_assert_nonnull (extract_test);
@@ -770,7 +985,7 @@
 }
 
 static void
-test_one_file_conflict_skip_file (void)
+test_conflict_skip_file (void)
 {
   /* arextract.zip
    * ????????? arextract.txt
@@ -791,7 +1006,7 @@
   g_autoptr (GFile) reference_file = NULL;
   g_autoptr (AutoarExtractor) extractor = NULL;
 
-  extract_test = extract_test_new ("test-one-file-conflict-skip-file");
+  extract_test = extract_test_new ("test-conflict-skip-file");
 
   if (!extract_test) {
     g_assert_nonnull (extract_test);
@@ -826,48 +1041,43 @@
   assert_reference_and_output_match (extract_test);
 }
 
+/* Be sure that the default action is skip to prevent data-loss. */
 static void
-test_one_file_error_file_over_directory (void)
+test_conflict_skip_file_default (void)
 {
-  /* The dummy file in this test is not relevant to the test itself, but it
-   * was required in order to add the directory to the .git repo
-   *
-   * arextract.zip
-   * ????????? arextract
+  /* arextract.zip
+   * ????????? arextract.txt
    *
    * 0 directories, 1 file
    *
    *
    * ref
-   * ????????? arextract
-   *     ????????? dummy
+   * ????????? arextract.txt
    *
-   * 1 directory, 1 files
+   * 0 directories, 1 file
    */
 
   g_autoptr (ExtractTest) extract_test = NULL;
   g_autoptr (ExtractTestData) data = NULL;
   g_autoptr (GFile) archive = NULL;
-  g_autoptr (GFile) conflict_directory = NULL;
-  g_autoptr (GFile) dummy_file = NULL;
-  g_autoptr (GFileOutputStream) out = NULL;
+  g_autoptr (GFile) conflict_file = NULL;
+  g_autoptr (GFile) reference_file = NULL;
   g_autoptr (AutoarExtractor) extractor = NULL;
 
-  extract_test = extract_test_new ("test-one-file-error-file-over-directory");
+  extract_test = extract_test_new ("test-conflict-skip-file-default");
 
   if (!extract_test) {
     g_assert_nonnull (extract_test);
     return;
   }
 
-  conflict_directory = g_file_get_child (extract_test->output,
-                                         "arextract");
-  dummy_file = g_file_get_child (conflict_directory, "dummy");
-
-  g_file_make_directory (conflict_directory, NULL, NULL);
+  reference_file = g_file_get_child (extract_test->reference,
+                                     "arextract.txt");
+  conflict_file = g_file_get_child (extract_test->output,
+                                    "arextract.txt");
 
-  out = g_file_create (dummy_file, G_FILE_CREATE_NONE, NULL, NULL);
-  g_output_stream_close (G_OUTPUT_STREAM (out), NULL, NULL);
+  g_file_copy (reference_file, conflict_file, G_FILE_COPY_NONE,
+               NULL, NULL, NULL, NULL);
 
   archive = g_file_get_child (extract_test->input, "arextract.zip");
 
@@ -875,12 +1085,16 @@
 
   data = extract_test_data_new_for_extract (extractor);
 
+  g_hash_table_insert (data->conflict_files_actions,
+                       g_object_ref (conflict_file),
+                       GUINT_TO_POINTER (AUTOAR_CONFLICT_UNHANDLED));
+
   autoar_extractor_start (extractor, data->cancellable);
 
   g_assert_cmpuint (data->number_of_files, ==, 1);
   g_assert_true (g_hash_table_contains (data->conflict_files,
-                                        conflict_directory));
-  g_assert_null (data->error);
+                                        conflict_file));
+  g_assert_no_error (data->error);
   g_assert_true (data->completed_signalled);
   assert_reference_and_output_match (extract_test);
 }
@@ -934,6 +1148,144 @@
   assert_reference_and_output_match (extract_test);
 }
 
+/* Be sure that the files with symlinks in parents are refused completely for
+ * security reasons.
+ *
+ * If symlinks in parents will be allowed in the future, then the following
+ * cases need to be tested to be sure that nothing is written outside of the
+ * destination:
+ * 1) link -> .. ; link/arextract.txt
+ * 2) link -> /tmp ; link/arextract.txt
+ * 3) current -> . ; link -> current/.. ; link/arextract.txt
+ * 4) tmplink -> /tmp ; link -> tmplink/.. ; link/arextract.txt
+ */
+static void
+test_symlink_parent (void)
+{
+  /* arextract.tar
+   * ????????? arextract -> /tmp
+   * ????????? arextract/arextract.txt
+   *
+   * 0 directories, 2 files
+   *
+   *
+   * ref
+   * ????????? arextract -> /tmp
+   *
+   * 0 directories, 1 file
+   */
+
+  g_autoptr (ExtractTest) extract_test = NULL;
+  g_autoptr (ExtractTestData) data = NULL;
+  g_autoptr (GFile) archive = NULL;
+  g_autoptr (AutoarExtractor) extractor = NULL;
+
+  extract_test = extract_test_new ("test-symlink-parent");
+
+  if (!extract_test) {
+    g_assert_nonnull (extract_test);
+    return;
+  }
+
+  archive = g_file_get_child (extract_test->input, "arextract.tar");
+
+  extractor = autoar_extractor_new (archive, extract_test->output);
+
+  data = extract_test_data_new_for_extract (extractor);
+
+  autoar_extractor_start (extractor, data->cancellable);
+
+  g_assert_cmpuint (data->number_of_files, ==, 2);
+  g_assert_error (data->error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY);
+  g_assert_false (data->completed_signalled);
+  assert_reference_and_output_match (extract_test);
+}
+
+/* Be sure that file with the ".." parent is written in the destination. */
+static void
+test_sanitize_dotdot_parent (void)
+{
+  /* arextract.tar
+   * ????????? ./../arextract.txt
+   *
+   * 0 directories, 1 file
+   *
+   *
+   * ref
+   * ????????? arextract.txt
+   *
+   * 0 directories, 1 file
+   */
+
+  g_autoptr (ExtractTest) extract_test = NULL;
+  g_autoptr (ExtractTestData) data = NULL;
+  g_autoptr (GFile) archive = NULL;
+  g_autoptr (AutoarExtractor) extractor = NULL;
+
+  extract_test = extract_test_new ("test-sanitize-dotdot-parent");
+
+  if (!extract_test) {
+    g_assert_nonnull (extract_test);
+    return;
+  }
+
+  archive = g_file_get_child (extract_test->input, "arextract.tar");
+
+  extractor = autoar_extractor_new (archive, extract_test->output);
+  autoar_extractor_set_output_is_dest (extractor, TRUE);
+
+  data = extract_test_data_new_for_extract (extractor);
+
+  autoar_extractor_start (extractor, data->cancellable);
+
+  g_assert_cmpuint (data->number_of_files, ==, 1);
+  g_assert_no_error (data->error);
+  g_assert_true (data->completed_signalled);
+  assert_reference_and_output_match (extract_test);
+}
+
+/* Be sure that the absolute paths are relative to the destination. */
+static void
+test_sanitize_absolute_path (void)
+{
+  /* arextract.tar
+   * ????????? /arextract.txt
+   *
+   * 0 directories, 1 file
+   *
+   *
+   * ref
+   * ????????? arextract.txt
+   *
+   * 0 directories, 1 file
+   */
+
+  g_autoptr (ExtractTest) extract_test = NULL;
+  g_autoptr (ExtractTestData) data = NULL;
+  g_autoptr (GFile) archive = NULL;
+  g_autoptr (AutoarExtractor) extractor = NULL;
+
+  extract_test = extract_test_new ("test-sanitize-absolute-path");
+
+  if (!extract_test) {
+    g_assert_nonnull (extract_test);
+    return;
+  }
+
+  archive = g_file_get_child (extract_test->input, "arextract.tar");
+
+  extractor = autoar_extractor_new (archive, extract_test->output);
+
+  data = extract_test_data_new_for_extract (extractor);
+
+  autoar_extractor_start (extractor, data->cancellable);
+
+  g_assert_cmpuint (data->number_of_files, ==, 1);
+  g_assert_no_error (data->error);
+  g_assert_true (data->completed_signalled);
+  assert_reference_and_output_match (extract_test);
+}
+
 static void
 setup_test_suite (void)
 {
@@ -941,23 +1293,37 @@
                    test_one_file_same_name);
   g_test_add_func ("/autoar-extract/test-one-file-different-name",
                    test_one_file_different_name);
+  g_test_add_func 
("/autoar-extract/test-one-file-different-name-output-is-dest",
+                   test_one_file_different_name_output_is_dest);
   g_test_add_func ("/autoar-extract/test-multiple-files-same-name",
                    test_multiple_files_same_name);
   g_test_add_func ("/autoar-extract/test-multiple-files-different-name",
                    test_multiple_files_different_name);
 
-  g_test_add_func ("/autoar-extract/test-one-file-conflict-overwrite",
-                   test_one_file_conflict_overwrite);
-  g_test_add_func ("/autoar-extract/test-one-file-conflict-new-destination",
-                   test_one_file_conflict_new_destination);
-  g_test_add_func ("/autoar-extract/test-one-file-conflict-skip-file",
-                   test_one_file_conflict_skip_file);
-
-  g_test_add_func ("/autoar-extract/test-one-file-error-file-over-directory",
-                   test_one_file_error_file_over_directory);
+  g_test_add_func ("/autoar-extract/test-conflict-overwrite",
+                   test_conflict_overwrite);
+  g_test_add_func 
("/autoar-extract/test-conflict-overwrite-nonempty-directory",
+                   test_conflict_overwrite_nonempty_directory);
+  g_test_add_func ("/autoar-extract/test-conflict-overwrite-symlink",
+                   test_conflict_overwrite_symlink);
+  g_test_add_func ("/autoar-extract/test-conflict-overwrite-hardlink",
+                   test_conflict_overwrite_hardlink);
+  g_test_add_func ("/autoar-extract/test-conflict-new-destination",
+                   test_conflict_new_destination);
+  g_test_add_func ("/autoar-extract/test-conflict-skip-file",
+                   test_conflict_skip_file);
+  g_test_add_func ("/autoar-extract/test-conflict-skip-file-default",
+                   test_conflict_skip_file_default);
 
   g_test_add_func ("/autoar-extract/test-change-extract-destination",
                    test_change_extract_destination);
+
+  g_test_add_func ("/autoar-extract/test-symlink-parent",
+                   test_symlink_parent);
+  g_test_add_func ("/autoar-extract/test-sanitize-dotdot-parent",
+                   test_sanitize_dotdot_parent);
+  g_test_add_func ("/autoar-extract/test-sanitize-absolute-path",
+                   test_sanitize_absolute_path);
 }
 
 int

Reply via email to