openSUSE Commits
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
October 2018
- 1 participants
- 1996 discussions
Hello community,
here is the log from the commit of package cozy for openSUSE:Factory checked in at 2018-10-29 14:23:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/cozy (Old)
and /work/SRC/openSUSE:Factory/.cozy.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cozy"
Mon Oct 29 14:23:01 2018 rev:4 rq:645176 version:0.6.1b
Changes:
--------
--- /work/SRC/openSUSE:Factory/cozy/cozy.changes 2018-09-11 17:18:33.519294051 +0200
+++ /work/SRC/openSUSE:Factory/.cozy.new/cozy.changes 2018-10-29 14:59:00.742027518 +0100
@@ -1,0 +2,6 @@
+Mon Oct 8 09:00:42 UTC 2018 - suse(a)geigi.de
+
+- Update to 0.6.1b:
+ * Fixed a bug which prevented cozy from automatically playing the next chapter
+
+-------------------------------------------------------------------
Old:
----
cozy-0.6.1.tar.gz
New:
----
cozy-0.6.1b.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ cozy.spec ++++++
--- /var/tmp/diff_new_pack.8gtko7/_old 2018-10-29 14:59:01.138027983 +0100
+++ /var/tmp/diff_new_pack.8gtko7/_new 2018-10-29 14:59:01.142027988 +0100
@@ -17,7 +17,7 @@
Name: cozy
-Version: 0.6.1
+Version: 0.6.1b
Release: 0
Summary: Audio Book Player
License: GPL-3.0-only
++++++ cozy-0.6.1.tar.gz -> cozy-0.6.1b.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/README.md new/cozy-0.6.1b/README.md
--- old/cozy-0.6.1/README.md 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/README.md 2018-10-10 23:29:43.000000000 +0200
@@ -85,6 +85,14 @@
```
## Q&A
+### I have imported wrong files and cannot get rid of them:
+Delete the following folders to reset cozy (this will loose all saved progress):
+```
+~/.local/share/cozy
+~/.cache/cozy
+```
+
+
### I can't uninstall the Flatpak:
Try
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/cozy/book_overview.py new/cozy-0.6.1b/cozy/book_overview.py
--- old/cozy-0.6.1/cozy/book_overview.py 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/cozy/book_overview.py 2018-10-10 23:29:43.000000000 +0200
@@ -194,10 +194,11 @@
return
if curr_track:
+ track_box_children = [e for e in self.track_box.get_children() if isinstance(e, TrackElement)]
self.current_track_element = next(
filter(
lambda x: x.track.id == curr_track.id,
- self.track_box.get_children()), None)
+ track_box_children), None)
if self.current_track_element is None:
self.current_track_element = self.track_box.get_children()[0]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/data/com.github.geigi.cozy.appdata.xml new/cozy-0.6.1b/data/com.github.geigi.cozy.appdata.xml
--- old/cozy-0.6.1/data/com.github.geigi.cozy.appdata.xml 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/data/com.github.geigi.cozy.appdata.xml 2018-10-10 23:29:43.000000000 +0200
@@ -53,6 +53,13 @@
<url type="donation">https://www.patreon.com/geigi</url>
<update_contact>cozy(a)geigi.de</update_contact>
<releases>
+ <release version="0.6.1b" timestamp="1539206841">
+ <description>
+ <ul>
+ <li>Fixed a bug which prevented cozy from automatically playing the next chapter</li>
+ </ul>
+ </description>
+ </release>
<release version="0.6.1" timestamp="1536329525">
<description>
<ul>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/debian/changelog new/cozy-0.6.1b/debian/changelog
--- old/cozy-0.6.1/debian/changelog 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/debian/changelog 1970-01-01 01:00:00.000000000 +0100
@@ -1,304 +0,0 @@
-com.github.geigi.cozy (0.6.1) UNSTABLE; urgency=low
-
- * Improved artwork image quality
- * The book overview now supports multiple disks in audiobooks
- * The file not found window will only open when the file is on the internal drive
- * Fixed a typo
- * Support for elementaryOS 5.0
- * Updated translations
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 07 Sep 2018 16:00:14 +0200
-
-com.github.geigi.cozy (0.6.0) UNSTABLE; urgency=low
-
- * Offline Mode! If your audiobooks are on an external or network drive, you can switch the download button to keep a local cached copy of the book to listen to on the go. To enable this feature you have to set your storage location to external in the settings.
- * Detect online/offline storage devices
- * Option to hide unavailable books
- * Support for wav files
- * Support for audio files that have no tags at all
- * You can mark books as read using the right click menu
- * New setting: Prefer cover image file over embedded covers
- * Redesigned Sleep Timer
- * More Sleep Timer: You can now stop the playback after the current chapter
- * And even more: Fadeout on timer end (in settings)
- * Redesigned hello screen and settings
- * Fixed bug where cozy would not start on GTK < 3.22
- * If no author field is present, the reader field will be used as author. This requires a force reimport (settings) on already imported books.
- * Optimizations under the hood
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 12 Jun 2018 10:03:14 +0200
-
-com.github.geigi.cozy (0.5.5) UNSTABLE; urgency=low
-
- * Import process is now a lot more robust
- * Importing should also be quite a bit faster now
- * You can now remove books from your library (using right click menu)
- * Blacklist for files that will not be displayed in the library
- * Cozy now prevents your system from suspend during playback
- * New app menu
- * Multiple bug fixes (30 second replay, last played text, ...)
- * UI fixes
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 29 Mar 2018 23:33:14 +0200
-
-com.github.geigi.cozy (0.5.4) UNSTABLE; urgency=low
-
- * One of cozys coolest releases yet
- * New book overview!
- * Lots of UI tweaks
- * HiDPI support
- * Dark mode can be enabled in settings
- * Fixed desktop integration (mpris)
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 09 Mar 2018 13:55:14 +0200
-
-com.github.geigi.cozy (0.5.3) UNSTABLE; urgency=low
-
- * Bugfix release
- * Changelog from 0.5.2:
- * Choose between displaying the current chapter or the whole book in the titlebar
- * Remember playback speed for each book
- * Press space to play and pause
- * Support for multiple storage locations!
- * Lots of work behind the scenes and small bug fixes
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 28 Feb 2018 10:13:14 +0200
-
-com.github.geigi.cozy (0.5.2) UNSTABLE; urgency=low
-
- * Choose between displaying the current chapter or the whole book in the titlebar
- * Remember playback speed for each book
- * Press space to play and pause
- * Support for multiple storage locations!
- * Lots of work behind the scenes and small bug fixes
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 27 Feb 2018 18:29:14 +0200
-
-com.github.geigi.cozy (0.5.1) UNSTABLE; urgency=low
-
- * Display the progress and remaining time of your books
- * Try clicking on the remaining time ;)
- * Support for album art in image files (thanks to oleg-krv)
- * Faster startup! (introducing album art cache)
- * Fixed mp3 disk number on imports
- * Other bugfixes
- * Some UI tweaks (thanks to jnbr)
- * Support for peewee3 (tanks to jnbr)
- * Chinese translation
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 12 Feb 2018 18:35:14 +0200
-
-com.github.geigi.cozy (0.5.0) UNSTABLE; urgency=low
-
- * Display the progress and remaining time of your books
- * Try clicking on the remaining time ;)
- * Support for album art in image files (thanks to oleg-krv)
- * Faster startup! (introducing album art cache)
- * Fixed mp3 disk number on imports
- * Other bugfixes
- * Some UI tweaks (thanks to jnbr)
- * Support for peewee3 (tanks to jnbr)
- * Chinese translation
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 12 Feb 2018 18:35:14 +0200
-
-com.github.geigi.cozy (0.4.9) UNSTABLE; urgency=low
-
- * Display the progress and remaining time of your books
- * Try clicking on the remaining time ;)
- * Support for album art in image files (thanks to oleg-krv)
- * Faster startup! (introducing album art cache)
- * Fixed mp3 disk number on imports
- * Other bugfixes
- * Some UI tweaks (thanks to jnbr)
- * Support for peewee3 (tanks to jnbr)
- * Chinese translation
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 12 Feb 2018 18:35:14 +0200
-
-com.github.geigi.cozy (0.4.8) UNSTABLE; urgency=low
-
- * Display the progress and remaining time of your books
- * Try clicking on the remaining time ;)
- * Support for album art in image files (thanks to oleg-krv)
- * Faster startup! (introducing album art cache)
- * Fixed mp3 disk number on imports
- * Other bugfixes
- * Some UI tweaks (thanks to jnbr)
- * Support for peewee3 (tanks to jnbr)
- * Chinese translation
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 12 Feb 2018 18:35:14 +0200
-
-com.github.geigi.cozy (0.4.7) UNSTABLE; urgency=low
-
- * Thanks to the translators for the new languages: Danish, Spanish, Finnish, Italian, Malay, Polish, Portuguese!
- * Faster startup! Especially with a lot of books cozy starts now way faster then before.
- * Fixed ogg tag reading. Please re-import your oggs!
- * Fixed a bug that could cause crashing cozy with modified playback speed
- * Fixed crackling when changing the playback speed
- * Fixed a bug where UI buttons would not get unlocked after a rescan
- * Fixed a bug where cozy would not stop playing on closing via menu
- * Fixed more bugs after a database rescan
- * Fixed a bug where track position was not updated after it finished playing
- * Fixed some minor UI bugs
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 09 Jan 2018 19:11:14 +0200
-
-com.github.geigi.cozy (0.4.6) UNSTABLE; urgency=low
-
- * Playback speed control!
- * New icons
- * Added French, Danish & Turkish translations! (Thanks to Vistaus, Distil62, karaagac)
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 12 Dec 2017 19:25:14 +0200
-
-com.github.geigi.cozy (0.4.4) UNSTABLE; urgency=low
-
- * Cozy now looks a lot nicer!
- * Lots of bug fixes
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 08 Dec 2017 01:05:14 +0200
-
-com.github.geigi.cozy (0.4.3) UNSTABLE; urgency=low
-
- * Updated russian translation
- * Fixed bug where cozy could crash on startup when a album cover is not supported
- * Track progressbar can now be controlled by the keyboard and supports incremental changes
- * Fixed a bug where the position of the track was not resetted after the playback finished
- * Probably faster import
- * Refactoring
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 04 Dec 2017 18:45:14 +0200
-
-com.github.geigi.cozy (0.4.2) UNSTABLE; urgency=low
-
- * Russian translation
- * Search your library!
- * More robust importer - notifies you about files that could not be imported
- * UI tweaks
- * Fixed a bug where the importer could crash
- * Added lots of tooltips
- * Started implementing orca screen reader support
- * Removed hello window
- * Lots of behind the scenes changes
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 26 Nov 2017 19:59:14 +0200
-
-com.github.geigi.cozy (0.4.1) UNSTABLE; urgency=low
-
- * Russian translation
- * Search your library!
- * More robust importer - notifies you about files that could not be imported
- * UI tweaks
- * Fixed a bug where the importer could crash
- * Lots of behind the scenes changes
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 24 Nov 2017 19:14:14 +0200
-
-com.github.geigi.cozy (0.4.0) UNSTABLE; urgency=low
-
- * The sleep timer has landed!
- * m4a/mp4 support!
- * Lots of UI improvements
- * More reliable playback
- * Fixed bug where tracks would appear twice in older GTK versions
- * More robust importing
- * New dialog when a file could not be found
- * Homepage URL is now corrected
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 10 Nov 2017 11:57:14 +0200
-
-com.github.geigi.cozy (0.3.5) UNSTABLE; urgency=low
-
- * Fixed peewee dependency install location
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 02 Nov 2017 00:40:14 +0200
-
-com.github.geigi.cozy (0.3.4) UNSTABLE; urgency=low
-
- * Dependency fixes
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 01 Nov 2017 16:32:14 +0200
-
-com.github.geigi.cozy (0.3.3) UNSTABLE; urgency=low
-
- * App Center build fix
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 01 Nov 2017 16:32:14 +0200
-
-com.github.geigi.cozy (0.3.2) UNSTABLE; urgency=low
-
- * App Center build fix
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 01 Nov 2017 16:01:14 +0200
-
-com.github.geigi.cozy (0.3.1) UNSTABLE; urgency=low
-
- * App Center build fix
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 01 Nov 2017 15:52:14 +0200
-
-com.github.geigi.cozy (0.3.0) UNSTABLE; urgency=low
-
- * App Center build fix
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 01 Nov 2017 15:26:14 +0200
-
-com.github.geigi.cozy (0.2.9) UNSTABLE; urgency=low
-
- * Fixed debian build?
-
- -- Julian Geywitz <github(a)geigi.de> Wed, 01 Nov 2017 15:26:14 +0200
-
-com.github.geigi.cozy (0.2.8) UNSTABLE; urgency=low
-
- * Fixed debian build
-
- -- Julian Geywitz <github(a)geigi.de> Mon, 30 Oct 2017 20:28:14 +0200
-
-com.github.geigi.cozy (0.2.7) UNSTABLE; urgency=low
-
- * Fixed debian runtime dependencies
-
- -- Julian Geywitz <github(a)geigi.de> Mon, 30 Oct 2017 17:08:14 +0200
-
-com.github.geigi.cozy (0.2.6) UNSTABLE; urgency=low
-
- * UI fixes in hello screen
- * Small bug fixes
- * New screenshots for app center
- * Contributors and patrons will now be added to the about window
-
- -- Julian Geywitz <github(a)geigi.de> Mon, 30 Oct 2017 13:08:14 +0200
-
-com.github.geigi.cozy (0.2.5) UNSTABLE; urgency=low
-
- * Do not use default_width and default_height properties
- * Smaller HeaderBar height
- * Use open-menu-symbolic for preferences button
- * Instructions if there are no files in library
- * About dialog now quitable
- * Optional auto-rescan the directory on startup
- * Bugfixes & ui tweaks
-
- -- Julian Geywitz <github(a)geigi.de> Sat, 28 Oct 2017 00:04:14 +0200
-
-com.github.geigi.cozy (0.2.3) UNSTABLE; urgency=low
-
- * Some UI changes
- * New playback hover icon
-
- -- Julian Geywitz <github(a)geigi.de> Thu, 23 Oct 2017 16:03:14 +0200
-
-com.github.geigi.cozy (0.2.2) UNSTABLE; urgency=low
-
- * Fixed missing tracklist in ui
-
- -- Julian Geywitz <github(a)geigi.de> Thu, 22 Oct 2017 16:19:14 +0200
-
-com.github.geigi.cozy (0.2.0) UNSTABLE; urgency=low
-
- * Getting the App Center integration running
-
- -- Julian Geywitz <github(a)geigi.de> Thu, 22 Oct 2017 13:45:14 +0200
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/debian/compat new/cozy-0.6.1b/debian/compat
--- old/cozy-0.6.1/debian/compat 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/debian/compat 1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/debian/control new/cozy-0.6.1b/debian/control
--- old/cozy-0.6.1/debian/control 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/debian/control 1970-01-01 01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
-Source: com.github.geigi.cozy
-Section: multimedia
-Priority: optional
-Maintainer: Julian Geywitz <github(a)geigi.de>
-Build-Depends: debhelper (>= 9),
- meson (>=0.40.0),
- libgtk-3-dev,
- python3,
- python3-pip,
- python3-setuptools,
- sed
-
-Standards-Version: 3.9.6
-Package: com.github.geigi.cozy
-Architecture: any
-Depends: ${misc:Depends},${shlibs:Depends},python3,python3-mutagen,python3-cairo,python3-gst-1.0,file,libgstreamer1.0-0,libgstreamer-plugins-base1.0-0,gstreamer1.0-plugins-good
-Pre-Depends: dpkg (>= 1.15.6)
-Description: Cozy
- A modern audiobook player
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/debian/copyright new/cozy-0.6.1b/debian/copyright
--- old/cozy-0.6.1/debian/copyright 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/debian/copyright 1970-01-01 01:00:00.000000000 +0100
@@ -1,32 +0,0 @@
-Upstream Author(s):
-
- Julian Geywitz <github(a)geigi.de>
-
-
-Copyright:
-
- Copyright (C) 2017 Julian Geywitz
-
-License:
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This package is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-On Debian systems, the complete text of the GNU General
-Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
-
-The Debian packaging is:
-
- Copyright (C) 2014 Cody Garver <codygarver(a)gmail.com>
-
-and is licensed under the GPL version 3, see above.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/debian/rules new/cozy-0.6.1b/debian/rules
--- old/cozy-0.6.1/debian/rules 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/debian/rules 1970-01-01 01:00:00.000000000 +0100
@@ -1,42 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-# Enable additional explot mitigation
-# (PIE and *full* RELRO at the time of this writing)
-#export DEB_BUILD_MAINT_OPTIONS=hardening=+all
-
-%:
- dh $@
-
-
-override_dh_auto_clean:
- rm -rf debian/build
-
-override_dh_auto_configure:
- mkdir -p debian/build
- mkdir -p peewee
- PYTHONUSERBASE=${CURDIR}/peewee pip3 install --user peewee
- cd debian/build && meson --prefix=/usr ../..
-
-DIRS = .
-FILES = $(shell find -type f -name '*.*')
-
-override_dh_auto_build:
- # Fix for meson 0.44.0
- #ls -al
- #sed -i -e 's%/data/ui/data/ui%/data/ui%g' $(FILES)
- #sed -i -e 's%/data/img/data/img%/data/img%g' $(FILES)
- cd debian/build && ninja -v
-
-override_dh_auto_install:
- cd debian/build && DESTDIR=${CURDIR}/debian/com.github.geigi.cozy ninja install
-
-override_dh_usrlocal:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/debian/source/format new/cozy-0.6.1b/debian/source/format
--- old/cozy-0.6.1/debian/source/format 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/debian/source/format 1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-3.0 (native)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/docs/README.md new/cozy-0.6.1b/docs/README.md
--- old/cozy-0.6.1/docs/README.md 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/docs/README.md 2018-10-10 23:29:43.000000000 +0200
@@ -67,6 +67,13 @@
# Q&A
+## I have imported wrong files and cannot get rid of them:
+Delete the following folders to reset cozy (this will loose all saved progress):
+```
+~/.local/share/cozy
+~/.cache/cozy
+```
+
## I can't uninstall the Flatpak:
Try
@@ -110,4 +117,4 @@
- mardojai
- trampover
-To nedrichards for the Flatpak.
\ No newline at end of file
+To nedrichards for the Flatpak.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cozy-0.6.1/meson.build new/cozy-0.6.1b/meson.build
--- old/cozy-0.6.1/meson.build 2018-09-07 16:15:46.000000000 +0200
+++ new/cozy-0.6.1b/meson.build 2018-10-10 23:29:43.000000000 +0200
@@ -1,5 +1,5 @@
project('cozy',
- version: '0.6.1',
+ version: '0.6.1b',
meson_version: '>= 0.40.0')
project_name = 'cozy'
1
0
Hello community,
here is the log from the commit of package lollypop for openSUSE:Factory checked in at 2018-10-29 14:22:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lollypop (Old)
and /work/SRC/openSUSE:Factory/.lollypop.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "lollypop"
Mon Oct 29 14:22:54 2018 rev:54 rq:645113 version:0.9.610
Changes:
--------
--- /work/SRC/openSUSE:Factory/lollypop/lollypop.changes 2018-10-26 11:10:59.741661169 +0200
+++ /work/SRC/openSUSE:Factory/.lollypop.new/lollypop.changes 2018-10-29 14:58:59.546026098 +0100
@@ -1,0 +2,9 @@
+Sun Oct 28 17:55:05 UTC 2018 - antoine.belvire(a)opensuse.org
+
+- Update to version 0.9.610:
+ * Fix broken MTP sync on GNOME 3.30 (glgo#World/lollypop#1522).
+ * Fix a crash about album discs (glgo#World/lollypop#1511).
+ * Fix broken radio view (glgo#World/lollypop#1529).
+- Remove useless runtime dependency on gobject-introspection.
+
+-------------------------------------------------------------------
Old:
----
lollypop-0.9.609.tar.xz
New:
----
lollypop-0.9.610.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ lollypop.spec ++++++
--- /var/tmp/diff_new_pack.w3Ln78/_old 2018-10-29 14:59:00.198026875 +0100
+++ /var/tmp/diff_new_pack.w3Ln78/_new 2018-10-29 14:59:00.206026885 +0100
@@ -16,9 +16,8 @@
#
-%global gobject_introspection_version 1.35.9
Name: lollypop
-Version: 0.9.609
+Version: 0.9.610
Release: 0
Summary: GNOME music playing application
License: GPL-3.0-or-later
@@ -31,12 +30,11 @@
BuildRequires: meson >= 0.41
BuildRequires: pkgconfig
BuildRequires: python3-devel
-BuildRequires: pkgconfig(gobject-introspection-1.0) >= %{gobject_introspection_version}
+BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.35.9
BuildRequires: pkgconfig(gtk+-3.0) >= 3.20
# Can't migrate to GDBus, the server-side support is not implemented yet:
# https://bugzilla.gnome.org/show_bug.cgi?id=656330
Requires: dbus-1-python3
-Requires: gobject-introspection >= %{gobject_introspection_version}
Requires: gstreamer-plugins-base
Requires: python3-beautifulsoup4
Requires: python3-cairo
++++++ _service ++++++
--- /var/tmp/diff_new_pack.w3Ln78/_old 2018-10-29 14:59:00.234026918 +0100
+++ /var/tmp/diff_new_pack.w3Ln78/_new 2018-10-29 14:59:00.234026918 +0100
@@ -1,7 +1,7 @@
<services>
<service mode="disabled" name="tar_scm">
<param name="changesgenerate">enable</param>
- <param name="revision">0.9.609</param>
+ <param name="revision">0.9.610</param>
<param name="scm">git</param>
<param name="url">https://gitlab.gnome.org/World/lollypop.git</param>
<param name="versionformat">@PARENT_TAG@</param>
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.w3Ln78/_old 2018-10-29 14:59:00.250026937 +0100
+++ /var/tmp/diff_new_pack.w3Ln78/_new 2018-10-29 14:59:00.254026942 +0100
@@ -1,4 +1,4 @@
<servicedata>
<service name="tar_scm">
<param name="url">https://gitlab.gnome.org/World/lollypop.git</param>
- <param name="changesrevision">eee4683f8a1e94bd5ac330855f3372c3f10b7fc1</param></service></servicedata>
\ No newline at end of file
+ <param name="changesrevision">76fcc86c22c0df02c644be78368efe6255199cbe</param></service></servicedata>
\ No newline at end of file
++++++ lollypop-0.9.609.tar.xz -> lollypop-0.9.610.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/data/DeviceManagerView.ui new/lollypop-0.9.610/data/DeviceManagerView.ui
--- old/lollypop-0.9.609/data/DeviceManagerView.ui 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/data/DeviceManagerView.ui 2018-10-28 15:27:23.000000000 +0100
@@ -12,8 +12,9 @@
<object class="GtkGrid" id="device">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">center</property>
<property name="margin_top">2</property>
+ <property name="row_spacing">5</property>
+ <property name="column_spacing">5</property>
<child>
<object class="GtkButton" id="sync_btn">
<property name="visible">True</property>
@@ -21,7 +22,6 @@
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Synchronize to your device</property>
<property name="halign">center</property>
- <property name="valign">end</property>
<property name="margin_start">5</property>
<property name="margin_end">5</property>
<property name="image">image1</property>
@@ -29,8 +29,8 @@
<signal name="clicked" handler="_on_sync_clicked" swapped="no"/>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
@@ -38,13 +38,101 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
- <property name="valign">start</property>
<property name="margin_start">5</property>
<signal name="changed" handler="_on_memory_combo_changed" swapped="no"/>
</object>
<packing>
- <property name="left_attach">1</property>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="infobar">
+ <property name="can_focus">False</property>
+ <property name="message_type">error</property>
+ <property name="show_close_button">True</property>
+ <property name="revealed">False</property>
+ <signal name="response" handler="_on_infobar_response" swapped="no"/>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkLabel" id="error_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">label</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
<property name="top_attach">0</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
</packing>
</child>
</object>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/data/DeviceManagerWidget.ui new/lollypop-0.9.610/data/DeviceManagerWidget.ui
--- old/lollypop-0.9.609/data/DeviceManagerWidget.ui 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/data/DeviceManagerWidget.ui 2018-10-28 15:27:23.000000000 +0100
@@ -18,64 +18,6 @@
<property name="row_spacing">5</property>
<property name="column_spacing">5</property>
<child>
- <object class="GtkInfoBar" id="infobar">
- <property name="app_paintable">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="message_type">error</property>
- <property name="show_close_button">True</property>
- <signal name="response" handler="_on_response" swapped="no"/>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="infobar-action_area1">
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
- <property name="layout_style">end</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child internal-child="content_area">
- <object class="GtkBox" id="infobar-content_area1">
- <property name="can_focus">False</property>
- <property name="spacing">16</property>
- <child>
- <object class="GtkLabel" id="error-label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_start">10</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
<object class="GtkOverlay">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -130,7 +72,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">1</property>
+ <property name="top_attach">0</property>
</packing>
</child>
</object>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/data/org.gnome.Lollypop.appdata.xml.in new/lollypop-0.9.610/data/org.gnome.Lollypop.appdata.xml.in
--- old/lollypop-0.9.609/data/org.gnome.Lollypop.appdata.xml.in 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/data/org.gnome.Lollypop.appdata.xml.in 2018-10-28 15:27:23.000000000 +0100
@@ -27,11 +27,12 @@
</ul>
</description>
<releases>
- <release version="0.9.608" date="2018-10-24">
+ <release version="0.9.610" date="2018-10-28">
<description>
<ul>
- <li>Fix hang while updating collection</li>
- <li>Fix an issue with multiple disc albums</li>
+ <li>Fix broken MTP sync on GNOME 3.30</li>
+ <li>Fix a crash about album discs</li>
+ <li>Fix broken radio view</li>
</ul>
</description>
</release>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/container.py new/lollypop-0.9.610/lollypop/container.py
--- old/lollypop-0.9.609/lollypop/container.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/container.py 2018-10-28 15:27:23.000000000 +0100
@@ -776,11 +776,11 @@
self.__stop_current_view()
radios = Radios()
radio_ids = radios.get_ids()
+ view = RadiosView(radios)
if radio_ids:
- view = RadiosView(radios)
view.populate(radio_ids)
else:
- view = MessageView(_("No favorite radios"))
+ view.show_warning()
view.show()
return view
@@ -822,7 +822,7 @@
if child is not None:
child.destroy()
del self.__devices[dev.id]
- break
+ break
def __show_donation(self):
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/objects.py new/lollypop-0.9.610/lollypop/objects.py
--- old/lollypop-0.9.609/lollypop/objects.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/objects.py 2018-10-28 15:27:23.000000000 +0100
@@ -234,14 +234,6 @@
if artist_ids:
self.artist_ids = artist_ids
- def merge_discs(self):
- """
- Merge discs into one
- """
- tracks = self.tracks
- self._discs = [Disc(self, 0)]
- self._discs[0].set_tracks(tracks)
-
def move_track(self, track, index):
"""
Move track to index
@@ -252,6 +244,14 @@
self._tracks.remove(track)
self._tracks.insert(index, track)
+ def merge_discs(self):
+ """
+ Merge discs into one
+ """
+ tracks = self.tracks
+ self._discs = [Disc(self, 0)]
+ self._discs[0].set_tracks(tracks)
+
def set_tracks(self, tracks):
"""
Set album tracks
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/progressbar.py new/lollypop-0.9.610/lollypop/progressbar.py
--- old/lollypop-0.9.609/lollypop/progressbar.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/progressbar.py 2018-10-28 15:27:23.000000000 +0100
@@ -10,12 +10,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from gi.repository import Gtk
+from gi.repository import Gtk, GLib
class ProgressBar(Gtk.ProgressBar):
"""
- A smart progress bar
+ A smart/smooth FIFO progress bar
+ Many objects can register and must call set_fraction(1) to unregister
"""
def __init__(self):
@@ -24,6 +25,8 @@
"""
Gtk.ProgressBar.__init__(self)
self.__callers = []
+ self.__fraction = 0.0
+ self.__progress_running = False
def add(self, caller):
"""
@@ -36,13 +39,48 @@
def set_fraction(self, fraction, caller):
"""
Set fraction if caller is on top.
+ @param fraction as float
+ @param caller as object
"""
if not self.__callers:
return
if caller == self.__callers[0]:
self.show()
- Gtk.ProgressBar.set_fraction(self, fraction)
- if fraction == 1:
- self.__callers.remove(caller)
- self.hide()
- Gtk.ProgressBar.set_fraction(self, 0.0)
+ self.__fraction = fraction
+ if not self.__progress_running:
+ self.__progress_running = True
+ self.__progress_update(caller)
+
+#######################
+# PRIVATE #
+#######################
+ def __reset(self, caller):
+ """
+ Reset and hide progressbar
+ @param caller as object
+ """
+ self.hide()
+ self.__fraction = 0.0
+ Gtk.ProgressBar.set_fraction(self, 0.0)
+ self.__progress_running = False
+ self.__callers.remove(caller)
+
+ def __progress_update(self, caller):
+ """
+ Update progressbar smoothly
+ @param caller as object
+ """
+ if caller != self.__callers[0]:
+ self.__progress_running = False
+ return
+ current = self.get_fraction()
+ if self.__fraction < 1:
+ progress = (self.__fraction - current) / 10
+ else:
+ progress = 0.01
+ if current < self.__fraction:
+ Gtk.ProgressBar.set_fraction(self, current + progress)
+ if current < 1.0:
+ GLib.timeout_add(10, self.__progress_update, caller)
+ else:
+ GLib.timeout_add(1000, self.__reset, caller)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/search.py new/lollypop-0.9.610/lollypop/search.py
--- old/lollypop-0.9.609/lollypop/search.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/search.py 2018-10-28 15:27:23.000000000 +0100
@@ -180,6 +180,7 @@
for key in album_tracks.keys():
(album, tracks, score) = album_tracks[key]
album.set_tracks(tracks)
+ album.merge_discs()
albums.append((score, album, True))
albums.sort(key=lambda tup: tup[0], reverse=True)
return albums
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/sync_mtp.py new/lollypop-0.9.610/lollypop/sync_mtp.py
--- old/lollypop-0.9.609/lollypop/sync_mtp.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/sync_mtp.py 2018-10-28 15:27:23.000000000 +0100
@@ -10,7 +10,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from gi.repository import GLib, Gio, Gst
+from gi.repository import GLib, Gio, Gst, GObject
from time import sleep
from re import match
@@ -35,21 +35,21 @@
loaded before entering the scope and saving it when exiting.
"""
- def __init__(self, base_uri):
+ def __init__(self):
"""
Constructor for MtpSyncDb
- @param base_uri as str
"""
- self.__base_uri = base_uri
- self.__db_uri = self.__base_uri + "/lollypop-sync.db"
self.__encoder = "convert_none"
self.__normalize = False
self.__metadata = {}
- def load_db(self):
+ def load(self, base_uri):
"""
Loads the metadata db from the MTP device
+ @param base_uri as str
"""
+ self.__base_uri = base_uri
+ self.__db_uri = self.__base_uri + "/lollypop-sync.db"
Logger.debug("MtpSyncDb::__load_db()")
try:
dbfile = Gio.File.new_for_uri(self.__db_uri)
@@ -67,27 +67,28 @@
Logger.info("MtpSyncDb::__load_db():"
" unknown sync db version")
except Exception as e:
- Logger.error("MtpSyncDb::load_db(): %s" % e)
+ Logger.error("MtpSyncDb::load(): %s" % e)
- def save_db(self):
+ def save(self):
"""
Saves the metadata db to the MTP device
"""
- Logger.debug("MtpSyncDb::__save_db()")
- jsondb = json.dumps({"version": 1,
+ try:
+ Logger.debug("MtpSyncDb::__save()")
+ jsondb = json.dumps(
+ {"version": 1,
"encoder": self.__encoder,
"normalize": self.__normalize,
"tracks_metadata": [
{"uri": x, "metadata": y}
for x, y in sorted(self.__metadata.items())]})
- dbfile = Gio.File.new_for_uri(self.__db_uri)
- ok, _ = dbfile.replace_contents(
- jsondb.encode("utf-8"),
- None, False,
- Gio.FileCreateFlags.REPLACE_DESTINATION,
- None)
- if not ok:
- Logger.error("MtpSyncDb::save_db() failed")
+ dbfile = Gio.File.new_for_uri(self.__db_uri)
+ (tmpfile, stream) = Gio.File.new_tmp()
+ stream.get_output_stream().write_all(jsondb.encode("utf-8"))
+ tmpfile.copy(dbfile, Gio.FileCopyFlags.OVERWRITE, None, None)
+ stream.close()
+ except Exception as e:
+ Logger.error("MtpSyncDb::__save(): %s", e)
def set_encoder(self, encoder):
"""
@@ -160,12 +161,15 @@
return uri
-# TODO Rework this code: was designed
-# for playlists and then for albums, it sucks!
-class MtpSync:
+class MtpSync(GObject.Object):
"""
Synchronisation to MTP devices
"""
+ __gsignals__ = {
+ "sync-progress": (GObject.SignalFlags.RUN_FIRST, None, (float,)),
+ "sync-finished": (GObject.SignalFlags.RUN_FIRST, None, ()),
+ "sync-errors": (GObject.SignalFlags.RUN_FIRST, None, (str,)),
+ }
__ENCODE_START = 'filesrc location="%s" ! decodebin\
! audioconvert\
@@ -195,28 +199,18 @@
"""
Init MTP synchronisation
"""
- self._syncing = False
- self.__errors = False
+ GObject.Object.__init__(self)
+ self.__cancellable = Gio.Cancellable()
+ self.__cancellable.cancel()
self.__errors_count = 0
- self._uri = ""
+ self.__last_error = ""
+ self.__uri = None
self.__total = 0 # Total files to sync
self.__done = 0 # Handled files on sync
- self._fraction = 0.0
self.__copied_art_uris = []
- self.__mtp_syncdb = MtpSyncDb("")
+ self.__mtp_syncdb = MtpSyncDb()
-#######################
-# PROTECTED #
-#######################
- def _load_db_uri(self, uri):
- """
- Load mtp db at URI
- @param uri as str
- """
- self.__mtp_syncdb = MtpSyncDb(uri)
- self.__mtp_syncdb.load_db()
-
- def _check_encoder_status(self, encoder):
+ def check_encoder_status(self, encoder):
"""
Check encoder status
@param encoder as str
@@ -226,39 +220,25 @@
return True
return False
- def _update_progress(self):
- """
- Update progress bar. Do nothing
- """
- pass
-
- def _on_finished(self):
- """
- Clean on finished. Do nothing
- """
- pass
-
- def _sync(self):
+ def sync(self, uri):
"""
Sync playlists with device. If playlists contains Type.NONE,
sync albums marked as to be synced
+ @param uri as str
"""
try:
- self.__in_thread = True
+ self.__uri = uri
+ self.__cancellable.reset()
self.__convert_bitrate = App().settings.get_value(
"convert-bitrate").get_int32()
- self.__errors = False
self.__errors_count = 0
self.__copied_art_uris = []
# For progress bar
self.__total = 1
self.__done = 0
- self._fraction = 0.0
playlists = []
- GLib.idle_add(App().window.container.progress.set_fraction,
- 0, self)
-
+ Logger.debug("Get new tracks before sync")
# New tracks for synced albums
album_ids = App().albums.get_synced_ids()
for album_id in album_ids:
@@ -269,53 +249,71 @@
playlists.append(App().playlists.get_name(playlist_id))
self.__total += len(App().playlists.get_tracks(playlist_id))
+ Logger.debug("Get old tracks")
# Old tracks
try:
children = self.__get_track_files()
self.__total += len(children)
except:
pass
- GLib.idle_add(self._update_progress)
# Copy new tracks to device
- if self._syncing:
+ if not self.__cancellable.is_cancelled():
+ Logger.debug("Sync albums")
self.__sync_albums()
+ Logger.debug("Sync playlists")
self.__sync_playlists(playlist_ids)
# Remove old tracks from device
- if self._syncing:
+ if not self.__cancellable.is_cancelled():
+ Logger.debug("Remove from device")
self.__remove_from_device(playlist_ids)
# Remove empty dirs
- self.__remove_empty_dirs()
-
- # Remove old playlists
- d = Gio.File.new_for_uri(self._uri)
- infos = d.enumerate_children(
- "standard::name",
- Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
- None)
- for info in infos:
- name = info.get_name()
- if name.endswith(".m3u") and name[:-4] not in playlists:
- f = infos.get_child(info)
- self.__retry(f.delete, (None,))
+ if not self.__cancellable.is_cancelled():
+ Logger.debug("Remove empty dirs")
+ self.__remove_empty_dirs()
+
+ if not self.__cancellable.is_cancelled():
+ Logger.debug("Remove old playlists")
+ # Remove old playlists
+ d = Gio.File.new_for_uri(self.__uri)
+ infos = d.enumerate_children(
+ "standard::name",
+ Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+ None)
+ for info in infos:
+ name = info.get_name()
+ if name.endswith(".m3u") and name[:-4] not in playlists:
+ f = infos.get_child(info)
+ self.__retry(f.delete, (None,))
- d = Gio.File.new_for_uri(self._uri + "/unsync")
+ Logger.debug("Create unsync")
+ d = Gio.File.new_for_uri(self.__uri + "/unsync")
if not d.query_exists():
self.__retry(d.make_directory_with_parents, (None,))
except Exception as e:
- Logger.error("DeviceManagerWidget::_sync(): %s" % e)
+ Logger.error("MtpSync::__sync(): %s" % e)
finally:
- self.__mtp_syncdb.save_db()
- self._fraction = 1.0
- self._syncing = False
- self.__in_thread = False
- if self.__errors:
- GLib.idle_add(self.__on_errors)
+ Logger.debug("Save sync db")
+ self.__mtp_syncdb.save()
+ self.__cancellable.cancel()
+ if self.__errors_count != 0:
+ Logger.debug("Sync errors")
+ GLib.idle_add(self.emit, "sync-errors", self.__last_error)
+ Logger.debug("Sync finished")
+ GLib.idle_add(self.emit, "sync-finished")
@property
- def mtp_syncdb(self):
+ def cancellable(self):
+ """
+ Get cancellable
+ @return Gio.Cancellable
+ """
+ return self.__cancellable
+
+ @property
+ def db(self):
"""
Get sync db
"""
@@ -324,39 +322,35 @@
############
# Private #
############
- def __retry(self, func, args, t=5):
+ def __retry(self, func, args):
"""
- Try to execute func 5 times
+ Try to execute func and handle errors
@param func as function
@param args as tuple
"""
# Max allowed errors
- if self.__errors_count > 10:
- self._syncing = False
- return
- if t == 0:
- self.__errors_count += 1
- self.__errors = True
+ if self.__errors_count > 5:
+ self.__cancellable.cancel()
return
try:
func(*args)
except Exception as e:
Logger.error("MtpSync::_retry(%s, %s): %s" % (func, args, e))
- for a in args:
- if isinstance(a, Gio.File):
- Logger.info(a.get_uri())
- sleep(5)
- self.__retry(func, args, t - 1)
+ self.__last_error = e
+ self.__errors_count += 1
+ sleep(1)
def __remove_empty_dirs(self):
"""
Delete empty dirs
"""
to_delete = []
- dir_uris = [self._uri]
+ dir_uris = [self.__uri]
try:
# First get all directories
while dir_uris:
+ if self.__cancellable.is_cancelled():
+ break
uri = dir_uris.pop(0)
d = Gio.File.new_for_uri(uri)
infos = d.enumerate_children(
@@ -364,6 +358,8 @@
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
None)
for info in infos:
+ if self.__cancellable.is_cancelled():
+ break
if info.get_file_type() == Gio.FileType.DIRECTORY:
if info.get_name() != "unsync":
f = infos.get_child(info)
@@ -383,6 +379,8 @@
to_delete.append(f.get_uri())
# Then delete
for d in to_delete:
+ if self.__cancellable.is_cancelled():
+ break
d = Gio.File.new_for_uri(d)
try:
d.delete()
@@ -393,15 +391,17 @@
def __get_track_files(self):
"""
- Return files in self._uri/tracks
+ Return files in self.__uri/tracks
@return [str]
"""
children = []
- dir_uris = [self._uri]
- d = Gio.File.new_for_uri(self._uri)
+ dir_uris = [self.__uri]
+ d = Gio.File.new_for_uri(self.__uri)
if not d.query_exists():
self.__retry(d.make_directory_with_parents, (None,))
while dir_uris:
+ if self.__cancellable.is_cancelled():
+ break
try:
uri = dir_uris.pop(0)
d = Gio.File.new_for_uri(uri)
@@ -410,6 +410,8 @@
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
None)
for info in infos:
+ if self.__cancellable.is_cancelled():
+ break
if info.get_file_type() == Gio.FileType.DIRECTORY:
if info.get_name() != "unsync":
f = infos.get_child(info)
@@ -430,22 +432,18 @@
@param track as Track
@return (str, str, str, bool)
"""
- if not self._syncing:
- self._fraction = 1.0
- self.__in_thread = False
- return
Logger.debug("MtpSync::__sync_track_id(): %s" % track.uri)
album_name = escape(track.album_name.lower())
is_compilation = track.album.artist_ids[0] == Type.COMPILATIONS
if is_compilation:
artists = None
on_device_album_uri = "%s/%s" %\
- (self._uri,
+ (self.__uri,
album_name)
else:
artists = escape(", ".join(track.album.artists).lower())
on_device_album_uri = "%s/%s_%s" %\
- (self._uri,
+ (self.__uri,
artists,
album_name)
@@ -471,7 +469,7 @@
# Check extension, if not mp3, convert
m = match(r".*(\.[^.]*)", track.uri)
ext = m.group(1)
- convert_ext = self.__EXTENSION[self.mtp_syncdb.encoder]
+ convert_ext = self.__EXTENSION[self.__mtp_syncdb.encoder]
if convert_ext is not None and ext != convert_ext:
convertion_needed = True
track_name = track_name.replace(ext, convert_ext)
@@ -500,7 +498,8 @@
bus.add_signal_watch()
bus.connect("message::eos", self.__on_bus_eos)
self.__encoding = True
- while self.__encoding and self._syncing:
+ while self.__encoding and\
+ not self.__cancellable.is_cancelled():
sleep(1)
bus.disconnect_by_func(self.__on_bus_eos)
pipeline.set_state(Gst.State.PAUSED)
@@ -523,7 +522,8 @@
else:
self.__done += 1
self.__done += 1
- self._fraction = self.__done / self.__total
+ GLib.idle_add(self.emit, "sync-progress",
+ self.__done / self.__total)
return (track_name, artists, album_name, is_compilation)
def __sync_albums(self):
@@ -533,6 +533,8 @@
album_ids = App().albums.get_synced_ids()
for album_id in album_ids:
for track_id in App().albums.get_track_ids(album_id):
+ if self.__cancellable.is_cancelled():
+ return
self.__sync_track_id(Track(track_id))
def __sync_playlists(self, playlist_ids):
@@ -541,6 +543,8 @@
@param playlist_ids as [int]
"""
for playlist_id in playlist_ids:
+ if self.__cancellable.is_cancelled():
+ break
m3u = None
stream = None
playlist = App().playlists.get_name(playlist_id)
@@ -561,6 +565,8 @@
track_ids = App().playlists.get_track_ids(playlist_id)
# Start copying
for track_id in track_ids:
+ if self.__cancellable.is_cancelled():
+ break
if track_id is None:
continue
track = Track(track_id)
@@ -583,7 +589,7 @@
if m3u is not None:
playlist = escape(playlist)
dst = Gio.File.new_for_uri(
- self._uri + "/" + playlist + ".m3u")
+ self.__uri + "/" + playlist + ".m3u")
self.__retry(m3u.move,
(dst, Gio.FileCopyFlags.OVERWRITE, None, None))
@@ -602,18 +608,18 @@
track_ids += App().playlists.get_track_ids(playlist_id)
# Get tracks uris
for track_id in track_ids:
- if not self._syncing:
- self._fraction = 1.0
- self.__in_thread = False
+ if self.__cancellable.is_cancelled():
+ break
+ if self.__cancellable.is_cancelled():
return
track = Track(track_id)
album_name = escape(track.album_name.lower())
if track.album.artist_ids[0] == Type.COMPILATIONS:
- on_device_album_uri = "%s/%s" % (self._uri,
+ on_device_album_uri = "%s/%s" % (self.__uri,
album_name)
else:
artists = escape(", ".join(track.album.artists).lower())
- on_device_album_uri = "%s/%s_%s" % (self._uri,
+ on_device_album_uri = "%s/%s_%s" % (self.__uri,
artists,
album_name)
f = Gio.File.new_for_uri(track.uri)
@@ -621,7 +627,7 @@
# Check extension, if converted, remove
m = match(r".*(\.[^.]*)", track.uri)
ext = m.group(1)
- convert_ext = self.__EXTENSION[self.mtp_syncdb.encoder]
+ convert_ext = self.__EXTENSION[self.__mtp_syncdb.encoder]
if convert_ext is not None and ext != convert_ext:
track_name = track_name.replace(ext, convert_ext)
dst_uri = "%s/%s" % (on_device_album_uri, track_name)
@@ -633,9 +639,7 @@
# Delete file on device and not in playlists
for uri in on_mtp_files:
- if not self._syncing:
- self._fraction = 1.0
- self.__in_thread = False
+ if self.__cancellable.is_cancelled():
return
Logger.debug("MtpSync::__remove_from_device(): %s" % uri)
if uri not in track_uris and uri not in self.__copied_art_uris:
@@ -645,7 +649,8 @@
self.__retry(to_delete.delete, (None,))
self.__mtp_syncdb.delete_uri(uri)
self.__done += 1
- self._fraction = self.__done / self.__total
+ GLib.idle_add(self.emit, "sync-progress",
+ self.__done / self.__total)
def __convert(self, src, dst):
"""
@@ -659,17 +664,17 @@
src_path = src.get_path().replace("\\", "\\\\\\")
dst_path = dst.get_path().replace("\\", "\\\\\\")
pipeline_str = self.__ENCODE_START % src_path
- if self.mtp_syncdb.normalize:
+ if self.__mtp_syncdb.normalize:
pipeline_str += self.__NORMALIZE
- if self.mtp_syncdb.encoder in ["convert_vorbis", "convert_aac"]:
+ if self.__mtp_syncdb.encoder in ["convert_vorbis", "convert_aac"]:
convert_bitrate = self.__convert_bitrate * 1000
else:
convert_bitrate = self.__convert_bitrate
try:
- pipeline_str += self.__ENCODERS[self.mtp_syncdb.encoder] %\
+ pipeline_str += self.__ENCODERS[self.__mtp_syncdb.encoder] %\
convert_bitrate
except:
- pipeline_str += self.__ENCODERS[self.mtp_syncdb.encoder]
+ pipeline_str += self.__ENCODERS[self.__mtp_syncdb.encoder]
pipeline_str += self.__ENCODE_END % dst_path
pipeline = Gst.parse_launch(pipeline_str)
pipeline.set_state(Gst.State.PLAYING)
@@ -685,9 +690,3 @@
@param message as Gst.Message
"""
self.__encoding = False
-
- def __on_errors(self):
- """
- Show something to the user. Do nothing.
- """
- pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/view_albums_list.py new/lollypop-0.9.610/lollypop/view_albums_list.py
--- old/lollypop-0.9.609/lollypop/view_albums_list.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/view_albums_list.py 2018-10-28 15:27:23.000000000 +0100
@@ -261,6 +261,12 @@
#######################
# PROTECTED #
#######################
+ def _on_populated(self):
+ """
+ Populate remaining discs
+ """
+ if len(self.discs) > 0:
+ TracksView.populate(self)
#######################
# PRIVATE #
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/view_device.py new/lollypop-0.9.610/lollypop/view_device.py
--- old/lollypop-0.9.609/lollypop/view_device.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/view_device.py 2018-10-28 15:27:23.000000000 +0100
@@ -84,8 +84,14 @@
self.__syncing_btn.set_label(_("Synchronize %s") % "")
builder.connect_signals(self)
self.__device_widget = DeviceManagerWidget(self)
- self.__device_widget.connect("sync-finished", self.__on_sync_finished)
+ self.__device_widget.mtp_sync.connect("sync-finished",
+ self.__on_sync_finished)
+ self.__device_widget.mtp_sync.connect("sync-errors",
+ self.__on_sync_errors)
self.__device_widget.show()
+ self.__infobar = builder.get_object("infobar")
+ self.__error_label = builder.get_object("error_label")
+
grid = builder.get_object("device")
self.add(grid)
self.add(self._scrolled)
@@ -123,7 +129,7 @@
Check if lollypop is syncing
@return bool
"""
- return self.__device_widget.is_syncing()
+ return not self.__device_widget.mtp_sync.cancellable.is_cancelled()
@property
def device(self):
@@ -136,6 +142,17 @@
#######################
# PROTECTED #
#######################
+ def _on_infobar_response(self, infobar, response_id):
+ """
+ Hide infobar
+ @param widget as Gtk.Infobar
+ @param reponse id as int
+ """
+ if response_id == Gtk.ResponseType.CLOSE:
+ self.__infobar.set_revealed(False)
+ # WTF?
+ GLib.timeout_add(300, self.__infobar.hide)
+
def _on_destroy(self, widget):
"""
Remove running timeout
@@ -151,8 +168,8 @@
Start synchronisation
@param widget as Gtk.Button
"""
- if self.__device_widget.is_syncing():
- self.__device_widget.cancel_sync()
+ if not self.__device_widget.mtp_sync.cancellable.is_cancelled():
+ self.__device_widget.mtp_sync.cancellable.cancel()
elif not App().window.container.progress.is_visible():
self.__memory_combo.hide()
self.__syncing_btn.set_label(_("Cancel synchronization"))
@@ -191,11 +208,20 @@
self.__device.uri = uri
def stop(self):
- """
- Stop syncing
- """
pass
+ def __on_sync_errors(self, mtp_sync, error):
+ """
+ Show information bar with error message
+ @param mtp_sync as MtpSync
+ @param error as str
+ """
+ error_text = error or _("Unknown error while syncing,"
+ " try to reboot your device")
+ self.__error_label.set_text(error_text)
+ self.__infobar.show()
+ self.__infobar.set_revealed(True)
+
def __on_sync_finished(self, device_widget):
"""
Restore widgets state
@@ -212,7 +238,7 @@
"""
# Just update device widget if already populated
if self.__memory_combo.get_active_text() is not None:
- if not self.__device_widget.is_syncing():
+ if self.__device_widget.mtp_sync.cancellable.is_cancelled():
self.__device_widget.populate(self.__selected_ids)
return
for text in text_list:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/view_radios.py new/lollypop-0.9.610/lollypop/view_radios.py
--- old/lollypop-0.9.609/lollypop/view_radios.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/view_radios.py 2018-10-28 15:27:23.000000000 +0100
@@ -12,11 +12,14 @@
from gi.repository import Gtk
+from gettext import gettext as _
+
from lollypop.view_flowbox import FlowBoxView
from lollypop.widgets_radio import RadioWidget
from lollypop.pop_radio import RadioPopover
from lollypop.pop_tunein import TuneinPopover
from lollypop.controller_view import ViewController
+from lollypop.view import MessageView
class RadiosView(FlowBoxView, ViewController):
@@ -44,6 +47,15 @@
self.connect_current_changed_signal()
self.connect_artwork_changed_signal("radio")
+ def show_warning(self):
+ """
+ Show a message to user
+ """
+ self._scrolled.hide()
+ view = MessageView(_("No favorite radios"))
+ view.show()
+ self.add(view)
+
#######################
# PROTECTED #
#######################
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/view_tracks.py new/lollypop-0.9.610/lollypop/view_tracks.py
--- old/lollypop-0.9.609/lollypop/view_tracks.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/view_tracks.py 2018-10-28 15:27:23.000000000 +0100
@@ -18,7 +18,7 @@
from lollypop.widgets_track import TracksWidget, TrackRow
from lollypop.objects import Album
from lollypop.logger import Logger
-from lollypop.define import App, Type, ResponsiveType, Shuffle, NextContext
+from lollypop.define import App, Type, Shuffle, NextContext
class TracksView:
@@ -58,10 +58,6 @@
self._tracks_widget_left = {}
self._tracks_widget_right = {}
- if self._responsive_type in [ResponsiveType.DND,
- ResponsiveType.LIST,
- ResponsiveType.SEARCH]:
- self._album.merge_discs()
# Discs to load, will be emptied
self.__discs = list(self._album.discs)
for disc in self.__discs:
@@ -274,6 +270,14 @@
return boxes
@property
+ def discs(self):
+ """
+ Get widget discs
+ @return [Discs]
+ """
+ return self.__discs
+
+ @property
def is_populated(self):
"""
Return True if populated
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/widgets_album.py new/lollypop-0.9.610/lollypop/widgets_album.py
--- old/lollypop-0.9.609/lollypop/widgets_album.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/widgets_album.py 2018-10-28 15:27:23.000000000 +0100
@@ -78,7 +78,7 @@
"""
True if overlayed or going to be
"""
- return self._show_overlay or self._timeout_id is not None
+ return self._show_overlay
#######################
# PROTECTED #
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/lollypop/widgets_device.py new/lollypop-0.9.610/lollypop/widgets_device.py
--- old/lollypop-0.9.609/lollypop/widgets_device.py 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/lollypop/widgets_device.py 2018-10-28 15:27:23.000000000 +0100
@@ -10,7 +10,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from gi.repository import Gtk, GLib, Gio, GObject, Pango
+from gi.repository import Gtk, GLib, Gio, Pango
from gettext import gettext as _
@@ -18,19 +18,13 @@
from lollypop.cellrenderer import CellRendererAlbum
from lollypop.define import App, Type
from lollypop.objects import Album
-from lollypop.logger import Logger
from lollypop.helper_task import TaskHelper
-# FIXME This class should not inherit MtpSync
-# TODO Rework MtpSync code
-class DeviceManagerWidget(Gtk.Bin, MtpSync):
+class DeviceManagerWidget(Gtk.Bin):
"""
Widget for synchronize mtp devices
"""
- __gsignals__ = {
- "sync-finished": (GObject.SignalFlags.RUN_FIRST, None, ())
- }
def __init__(self, parent):
"""
@@ -39,10 +33,11 @@
@param parent as Gtk.Widget
"""
Gtk.Bin.__init__(self)
- MtpSync.__init__(self)
+ self.__mtp_sync = MtpSync()
+ self.__mtp_sync.connect("sync-finished", self.__on_sync_finished)
+ self.__mtp_sync.connect("sync-progress", self.__on_sync_progress)
self.__parent = parent
- self.__stop = False
- self._uri = None
+ self.__uri = None
self.__builder = Gtk.Builder()
self.__builder.add_from_resource(
@@ -50,7 +45,6 @@
widget = self.__builder.get_object("widget")
self.connect("size-allocate", self.__on_size_allocate, widget)
- self.__error_label = self.__builder.get_object("error-label")
self.__switch_albums = self.__builder.get_object("switch_albums")
self.__menu_items = self.__builder.get_object("menu-items")
@@ -65,9 +59,6 @@
self.add(widget)
- self.__infobar = self.__builder.get_object("infobar")
- self.__infobar_label = self.__builder.get_object("infobarlabel")
-
renderer0 = Gtk.CellRendererToggle()
renderer0.set_property("activatable", True)
renderer0.connect("toggled", self.__on_item_toggled)
@@ -92,10 +83,8 @@
"""
Populate playlists or albums for selected_ids
@param selected_ids as [int]
- @thread safe
"""
self.__model.clear()
- self.__stop = False
if selected_ids[0] == Type.PLAYLISTS:
playlists = [(Type.LOVED, App().playlists.LOVED)]
playlists += App().playlists.get()
@@ -124,17 +113,17 @@
self.__switch_albums.disconnect_by_func(self.__on_albums_state_set)
except:
pass
- self._load_db_uri(uri)
- encoder = self.mtp_syncdb.encoder
- normalize = self.mtp_syncdb.normalize
+ self.__mtp_sync.db.load(uri)
+ encoder = self.__mtp_sync.db.encoder
+ normalize = self.__mtp_sync.db.normalize
self.__switch_normalize = self.__builder.get_object("switch_normalize")
self.__switch_normalize.set_sensitive(False)
self.__switch_normalize.set_active(normalize)
self.__builder.get_object(encoder).set_active(True)
- for encoder in self._GST_ENCODER.keys():
- if not self._check_encoder_status(encoder):
+ for encoder in self.__mtp_sync._GST_ENCODER.keys():
+ if not self.__mtp_sync.check_encoder_status(encoder):
self.__builder.get_object(encoder).set_sensitive(False)
- self._uri = uri
+ self.__uri = uri
d = Gio.File.new_for_uri(uri)
try:
if not d.query_exists():
@@ -142,52 +131,35 @@
except:
pass
- def is_syncing(self):
- """
- @return True if syncing
- """
- return self._syncing
-
def sync(self):
"""
Start synchronisation
"""
- self._syncing = True
App().window.container.progress.add(self)
self.__menu.set_sensitive(False)
self.__view.set_sensitive(False)
helper = TaskHelper()
- helper.run(self._sync)
+ helper.run(self.__mtp_sync.sync, self.__uri)
- def cancel_sync(self):
+ @property
+ def uri(self):
"""
- Cancel synchronisation
+ Get device uri
+ @return str
"""
- self._syncing = False
+ return self.__uri
-#######################
-# PROTECTED #
-#######################
- def _update_progress(self):
+ @property
+ def mtp_sync(self):
"""
- Update progress bar smoothly
+ MtpSync object
+ @return MtpSync
"""
- current = App().window.container.progress.get_fraction()
- if self._syncing:
- progress = (self._fraction - current) / 10
- else:
- progress = 0.01
- if current < self._fraction:
- App().window.container.progress.set_fraction(current + progress,
- self)
- if current < 1.0:
- if progress < 0.0002:
- GLib.timeout_add(500, self._update_progress)
- else:
- GLib.timeout_add(25, self._update_progress)
- else:
- GLib.timeout_add(1000, self._on_finished)
+ return self.__mtp_sync
+#######################
+# PROTECTED #
+#######################
def _pop_menu(self, button):
"""
Popup menu for album
@@ -202,35 +174,6 @@
popover.add(self.__menu_items)
popover.popup()
- def _on_finished(self):
- """
- Emit finished signal
- """
- MtpSync._on_finished(self)
- App().window.container.progress.set_fraction(1.0, self)
- self.__view.set_sensitive(True)
- self.__menu.set_sensitive(True)
- self.emit("sync-finished")
-
- def _on_errors(self):
- """
- Show information bar with error message
- """
- MtpSync._on_errors(self)
- error_text = _("Unknown error while syncing,"
- " try to reboot your device")
- try:
- d = Gio.File.new_for_uri(self._uri)
- info = d.query_filesystem_info("filesystem::free")
- free = info.get_attribute_as_string("filesystem::free")
-
- if free is None or int(free) < 1024:
- error_text = _("No free space available on device")
- except Exception as e:
- Logger.error("DeviceWidget::_on_errors(): %s" % e)
- self.__error_label.set_text(error_text)
- self.__infobar.show()
-
def _on_convert_toggled(self, widget):
"""
Save option
@@ -240,11 +183,11 @@
encoder = widget.get_name()
if encoder == "convert_none":
self.__switch_normalize.set_sensitive(False)
- self.mtp_syncdb.set_normalize(False)
- self.mtp_syncdb.set_encoder("convert_none")
+ self.__mtp_sync.db.set_normalize(False)
+ self.__mtp_sync.db.set_encoder("convert_none")
else:
self.__switch_normalize.set_sensitive(True)
- self.mtp_syncdb.set_encoder(encoder)
+ self.__mtp_sync.db.set_encoder(encoder)
def _on_normalize_state_set(self, widget, state):
"""
@@ -252,16 +195,7 @@
@param widget as Gtk.Switch
@param state as bool
"""
- self.mtp_syncdb.set_normalize(state)
-
- def _on_response(self, infobar, response_id):
- """
- Hide infobar
- @param widget as Gtk.Infobar
- @param reponse id as int
- """
- if response_id == Gtk.ResponseType.CLOSE:
- self.__infobar.hide()
+ self.__mtp_sync.db.set_normalize(state)
#######################
# PRIVATE #
@@ -272,7 +206,7 @@
@param playlists as [(int, str)]
@param synced_ids as [int]
"""
- if playlists and not self.__stop:
+ if playlists:
playlist = playlists.pop(0)
selected = playlist[0] in synced_ids
self.__model.append([selected, playlist[1], playlist[0]])
@@ -283,7 +217,7 @@
Append albums
@param albums as [int]
"""
- if albums and not self.__stop:
+ if albums:
album = Album(albums.pop(0))
synced = App().albums.get_synced(album.id)
# Do not sync youtube albums
@@ -346,3 +280,20 @@
"""
width = max(400, allocation.width / 2)
child_widget.set_size_request(width, -1)
+
+ def __on_sync_progress(self, mtp_sync, value):
+ """
+ Update progress bar
+ @param mtp_sync as MtpSync
+ @param value as float
+ """
+ App().window.container.progress.set_fraction(value, self)
+
+ def __on_sync_finished(self, mtp_sync):
+ """
+ Emit finished signal
+ @param mtp_sync as MtpSync
+ """
+ App().window.container.progress.set_fraction(1.0, self)
+ self.__view.set_sensitive(True)
+ self.__menu.set_sensitive(True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/meson.build new/lollypop-0.9.610/meson.build
--- old/lollypop-0.9.609/meson.build 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/meson.build 2018-10-28 15:27:23.000000000 +0100
@@ -1,5 +1,5 @@
project('lollypop',
- version: '0.9.609',
+ version: '0.9.610',
meson_version: '>= 0.40.0'
)
i18n = import('i18n')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lollypop-0.9.609/subprojects/po/ar.po new/lollypop-0.9.610/subprojects/po/ar.po
--- old/lollypop-0.9.609/subprojects/po/ar.po 2018-10-25 14:37:37.000000000 +0200
+++ new/lollypop-0.9.610/subprojects/po/ar.po 2018-10-28 15:27:23.000000000 +0100
@@ -8,8 +8,8 @@
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-10-09 18:44+0200\n"
-"PO-Revision-Date: 2018-10-23 16:22+0000\n"
-"Last-Translator: AbouZakaria <zakariakov(a)gmail.com>\n"
+"PO-Revision-Date: 2018-10-25 05:23+0000\n"
+"Last-Translator: mohammadA <mohammadAbdulhadi1(a)gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/gnumdk/lollypop/"
"ar/>\n"
"Language: ar\n"
@@ -30,7 +30,7 @@
#: ../data/org.gnome.Lollypop.gschema.xml:33
msgid "Window position"
-msgstr "موقع النافذة"
+msgstr "موضع النافذة"
#: ../data/org.gnome.Lollypop.gschema.xml:34
msgid "Window position (x and y)."
@@ -301,11 +301,12 @@
#: ../data/AboutDialog.ui.in:63 ../lollypop/container.py:834
msgid "Liberapay"
-msgstr "ليبرابي Liberapay"
+msgstr "ليبرابَي"
#: ../data/AboutDialog.ui.in:73 ../lollypop/container.py:834
+#, fuzzy
msgid "PayPal"
-msgstr "PayPal"
+msgstr "بايبال"
#: ../data/org.gnome.Lollypop.appdata.xml.in:7
#: ../data/org.gnome.Lollypop.desktop.in:3
@@ -435,15 +436,15 @@
#: ../data/Appmenu.ui:27
msgid "_Keyboard Shortcuts"
-msgstr "اختصارات _لوحة المفاتيح"
+msgstr "اختصارات لوحة ال_مفاتيح"
#: ../data/Appmenu.ui:31
msgid "_About"
-msgstr "_حول"
+msgstr "_عن"
#: ../data/Appmenu.ui:35
msgid "_Quit"
-msgstr "أ_غلق"
+msgstr "_غادر"
#: ../data/ArtistInformation.ui:108 ../lollypop/pop_menu.py:299
msgid "Show lyrics"
@@ -1326,7 +1327,7 @@
#: ../lollypop/view_playlists.py:205
msgid "Cancel"
-msgstr "إلغاء"
+msgstr "ألغ"
#: ../lollypop/view_playlists.py:291 ../lollypop/widgets_album_detailed.py:283
#, python-format
1
0
Hello community,
here is the log from the commit of package ansible for openSUSE:Factory checked in at 2018-10-29 14:22:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ansible (Old)
and /work/SRC/openSUSE:Factory/.ansible.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ansible"
Mon Oct 29 14:22:51 2018 rev:43 rq:645097 version:2.7.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/ansible/ansible.changes 2018-10-15 10:48:56.411037678 +0200
+++ /work/SRC/openSUSE:Factory/.ansible.new/ansible.changes 2018-10-29 14:58:58.298024590 +0100
@@ -1,0 +2,16 @@
+Sat Oct 27 03:22:44 UTC 2018 - sean(a)suspend.net
+
+- update to 2.7.1
+ Minor changes:
+ * Fix yum module to properly check for empty conf_file value
+ * added capability to set the scheme for the consul_kv lookup
+ * added optional certificate and certificate validation for consul_kv lookups
+ * dnf - properly handle modifying the enable/disable excludes data field
+ * dnf appropriately handles disable_excludes repoid argument
+ * dnf proerly honors disable_gpg_check for local package installation
+ * fix yum module to handle list argument optional empty strings properly
+ * netconf_config - Make default_operation optional in netconf_config module
+ * yum - properly handle proxy password and username embedded in url
+ * yum/dnf - fail when space separated string of names
+
+-------------------------------------------------------------------
Old:
----
ansible-2.7.0.tar.gz
New:
----
ansible-2.7.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ansible.spec ++++++
--- /var/tmp/diff_new_pack.qEURWG/_old 2018-10-29 14:58:59.318025825 +0100
+++ /var/tmp/diff_new_pack.qEURWG/_new 2018-10-29 14:58:59.318025825 +0100
@@ -36,7 +36,7 @@
BuildArch: noarch
%endif
Name: ansible
-Version: 2.7.0
+Version: 2.7.1
Release: 0
Summary: Software automation engine
License: GPL-3.0-or-later
++++++ ansible-2.7.0.tar.gz -> ansible-2.7.1.tar.gz ++++++
/work/SRC/openSUSE:Factory/ansible/ansible-2.7.0.tar.gz /work/SRC/openSUSE:Factory/.ansible.new/ansible-2.7.1.tar.gz differ: char 5, line 1
1
0
Hello community,
here is the log from the commit of package ldmtool for openSUSE:Factory checked in at 2018-10-29 14:22:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ldmtool (Old)
and /work/SRC/openSUSE:Factory/.ldmtool.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ldmtool"
Mon Oct 29 14:22:43 2018 rev:3 rq:645047 version:0.2.3
Changes:
--------
--- /work/SRC/openSUSE:Factory/ldmtool/ldmtool.changes 2017-06-12 15:31:44.406213479 +0200
+++ /work/SRC/openSUSE:Factory/.ldmtool.new/ldmtool.changes 2018-10-29 14:58:56.754022688 +0100
@@ -1,0 +2,7 @@
+Sat Oct 27 15:29:47 UTC 2018 - Liang Yan <lyan(a)suse.com>
+
+- fix deprecated api g_type_class_add_private()
+- Added patches:
+ * Remove-deprecated-g_type_class_add_private.patch
+
+-------------------------------------------------------------------
New:
----
Remove-deprecated-g_type_class_add_private.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ldmtool.spec ++++++
--- /var/tmp/diff_new_pack.i1doxw/_old 2018-10-29 14:58:57.154023185 +0100
+++ /var/tmp/diff_new_pack.i1doxw/_new 2018-10-29 14:58:57.158023190 +0100
@@ -1,7 +1,7 @@
#
# spec file for package ldmtool
#
-# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,7 +12,7 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
@@ -23,13 +23,14 @@
Version: 0.2.3
Release: 0
Summary: A tool to manage Windows dynamic disks
-License: GPL-3.0
+License: GPL-3.0-only
Group: System/Base
Url: https://github.com/mdbooth/libldm
Source0: %{url}/downloads/%{srcname}-%{version}.tar.gz
Patch0: werror-fixes.patch
Patch1: cast_be64toh.patch
+Patch2: Remove-deprecated-g_type_class_add_private.patch
BuildRequires: device-mapper-devel >= 1.0
BuildRequires: glib2-devel >= 2.26.0
@@ -48,7 +49,7 @@
%package -n %{srcname}-%{sover}
Summary: Library to manage Windows dynamic disks
-License: LGPL-3.0
+License: LGPL-3.0-only
Group: System/Libraries
%description -n %{srcname}-%{sover}
@@ -59,7 +60,7 @@
%package -n %{srcname}-%{sover}-devel
Summary: Development files for %{name}
-License: LGPL-3.0
+License: LGPL-3.0-only
Group: Development/Libraries/C and C++
Requires: %{srcname}-%{sover} = %{version}-%{release}
@@ -71,6 +72,7 @@
%setup -q -n %{srcname}-%{version}
%patch0 -p1
%patch1 -p1
+%patch2 -p1
%build
%configure --disable-static --enable-gtk-doc
++++++ Remove-deprecated-g_type_class_add_private.patch ++++++
>From f97b057e70b66bcf502a4923f64d8b999b5814c3 Mon Sep 17 00:00:00 2001
From: Liang Yan <lyan(a)suse.com>
Date: Sat, 27 Oct 2018 11:07:10 -0400
Subject: [PATCH] Remove deprecated g_type_class_add_private()
The API has been deprecated, which causes build failures,
use the G_DEFINE_TYPE_WITH_PRIVATE() macro instead.
Signed-off-by: Liang Yan <lyan(a)suse.com>
---
src/ldm.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/src/ldm.c b/src/ldm.c
index a55723c..1a9f2ec 100644
--- a/src/ldm.c
+++ b/src/ldm.c
@@ -271,7 +271,7 @@ struct _LDMPrivate
GArray *disk_groups;
};
-G_DEFINE_TYPE(LDM, ldm, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE(LDM, ldm, G_TYPE_OBJECT)
static void
ldm_dispose(GObject * const object)
@@ -296,7 +296,6 @@ ldm_class_init(LDMClass * const klass)
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->dispose = ldm_dispose;
- g_type_class_add_private(klass, sizeof(LDMPrivate));
}
/* LDMDiskGroup */
@@ -322,7 +321,7 @@ struct _LDMDiskGroupPrivate
GArray *comps;
};
-G_DEFINE_TYPE(LDMDiskGroup, ldm_disk_group, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE(LDMDiskGroup, ldm_disk_group, G_TYPE_OBJECT)
enum {
PROP_LDM_DISK_GROUP_PROP0,
@@ -392,7 +391,6 @@ ldm_disk_group_class_init(LDMDiskGroupClass * const klass)
object_class->finalize = ldm_disk_group_finalize;
object_class->get_property = ldm_disk_group_get_property;
- g_type_class_add_private(klass, sizeof(LDMDiskGroupPrivate));
/**
* LDMDiskGroup:guid:
@@ -487,7 +485,7 @@ struct _LDMVolumePrivate
guint32 _n_comps_i;
};
-G_DEFINE_TYPE(LDMVolume, ldm_volume, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE(LDMVolume, ldm_volume, G_TYPE_OBJECT)
enum {
PROP_LDM_VOLUME_PROP0,
@@ -573,7 +571,6 @@ ldm_volume_class_init(LDMVolumeClass * const klass)
object_class->finalize = ldm_volume_finalize;
object_class->get_property = ldm_volume_get_property;
- g_type_class_add_private(klass, sizeof(LDMVolumePrivate));
/**
* LDMVolume:name:
@@ -731,7 +728,7 @@ struct _LDMPartitionPrivate
LDMDisk *disk;
};
-G_DEFINE_TYPE(LDMPartition, ldm_partition, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE(LDMPartition, ldm_partition, G_TYPE_OBJECT)
enum {
PROP_LDM_PARTITION_PROP0,
@@ -792,7 +789,6 @@ ldm_partition_class_init(LDMPartitionClass * const klass)
object_class->finalize = ldm_partition_finalize;
object_class->get_property = ldm_partition_get_property;
- g_type_class_add_private(klass, sizeof(LDMPartitionPrivate));
/**
* LDMPartition:name:
@@ -866,7 +862,7 @@ struct _LDMDiskPrivate
gchar *device; // NULL until device is found
};
-G_DEFINE_TYPE(LDMDisk, ldm_disk, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE(LDMDisk, ldm_disk, G_TYPE_OBJECT)
enum {
PROP_LDM_DISK_PROP0,
@@ -944,7 +940,6 @@ ldm_disk_class_init(LDMDiskClass * const klass)
object_class->finalize = ldm_disk_finalize;
object_class->get_property = ldm_disk_get_property;
- g_type_class_add_private(klass, sizeof(LDMDiskPrivate));
/**
* LDMDisk:name:
--
2.19.1
1
0
Hello community,
here is the log from the commit of package clipgrab for openSUSE:Factory checked in at 2018-10-29 14:22:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/clipgrab (Old)
and /work/SRC/openSUSE:Factory/.clipgrab.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "clipgrab"
Mon Oct 29 14:22:47 2018 rev:5 rq:645052 version:3.7.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/clipgrab/clipgrab.changes 2018-04-17 11:18:00.373036762 +0200
+++ /work/SRC/openSUSE:Factory/.clipgrab.new/clipgrab.changes 2018-10-29 14:58:57.306023372 +0100
@@ -1,0 +2,7 @@
+Sat Oct 27 17:11:14 UTC 2018 - Luigi Baldoni <aloisio(a)gmx.com>
+
+- Update to version 3.7.1 (no changelog supplied)
+- Refreshed clipgrab-qt5.patch
+- Spec cleanup
+
+-------------------------------------------------------------------
Old:
----
clipgrab-3.6.8.tar.gz
New:
----
clipgrab-3.7.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ clipgrab.spec ++++++
--- /var/tmp/diff_new_pack.XGhxVd/_old 2018-10-29 14:58:57.710023871 +0100
+++ /var/tmp/diff_new_pack.XGhxVd/_new 2018-10-29 14:58:57.710023871 +0100
@@ -13,17 +13,17 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
Name: clipgrab
-Version: 3.6.8
+Version: 3.7.1
Release: 0
Summary: Video downloader
-License: GPL-3.0+
+License: GPL-3.0-or-later
Group: Productivity/Multimedia/Video/Editors and Convertors
-Url: https://clipgrab.org
+URL: https://clipgrab.org
Source0: https://download.clipgrab.org/%{name}-%{version}.tar.gz
Source1: %{name}.desktop
# PATCH-FIX-UPSTREAM clipgrab-qt5.patch aloisio(a)gmx.com -- build against Qt5
@@ -31,12 +31,12 @@
BuildRequires: ImageMagick
BuildRequires: hicolor-icon-theme >= 0.15
BuildRequires: openjpeg
+BuildRequires: pkgconfig
BuildRequires: update-desktop-files
BuildRequires: pkgconfig(Qt5WebKit)
BuildRequires: pkgconfig(Qt5WebKitWidgets)
BuildRequires: pkgconfig(Qt5Xml)
Requires: ffmpeg
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
%description
A program which downloads and converts online videos from YouTube, Vimeo,
@@ -55,10 +55,8 @@
for s in 16 32 128 256 ; do
convert -strip -resize ${s}x${s} 512.png ${s}.png
done
-#cleanup
-rm -f moc_*
-qmake-qt5 %{name}.pro QMAKE_CXXFLAGS="%{optflags}"
-make %{?_smp_mflags} clean
+
+%qmake5 %{name}.pro
make %{?_smp_mflags}
%install
@@ -69,15 +67,16 @@
done
%suse_update_desktop_file -r %{name} Video Editor
+%if 0%{?suse_version} < 1500
%post
%desktop_database_post
%postun
%desktop_database_postun
+%endif
%files
-%defattr(-,root,root,-)
-%doc COPYING
+%license COPYING
%{_bindir}/clipgrab
%{_datadir}/applications/%{name}.desktop
%{_datadir}/icons/hicolor/*/apps/%{name}.png
++++++ clipgrab-3.6.8.tar.gz -> clipgrab-3.7.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/.gitignore new/clipgrab-3.7.1/.gitignore
--- old/clipgrab-3.6.8/.gitignore 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/.gitignore 2018-10-03 08:13:44.000000000 +0200
@@ -7,6 +7,11 @@
*.o
moc_*.cpp
*.autosave
+*.swp
+*.log
qrc_resources.cpp
+*.pro.user*
+clipgrab-*.tar*
+clipgrab-*.zip*
build
ClipGrab.xcodeproj
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/ClipGrab.plist new/clipgrab-3.7.1/ClipGrab.plist
--- old/clipgrab-3.6.8/ClipGrab.plist 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/ClipGrab.plist 2018-10-03 08:13:44.000000000 +0200
@@ -17,6 +17,6 @@
<key>NSHighResolutionCapable</key>
<string>True</string>
<key>CFBundleVersion</key>
- <string>3.6.8</string>
+ <string>3.7.1</string>
</dict>
</plist>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/clipgrab-legacy.pro new/clipgrab-3.7.1/clipgrab-legacy.pro
--- old/clipgrab-3.6.8/clipgrab-legacy.pro 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/clipgrab-legacy.pro 2018-10-03 08:13:44.000000000 +0200
@@ -90,6 +90,6 @@
CONFIG += x86 ppc
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.5
}
-VERSION = 3.6.8
+VERSION = 3.7.1
DEFINES += MAC_LEGACY
DEFINES += CLIPGRAB_VERSION='"$${VERSION}"'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/clipgrab.cpp new/clipgrab-3.7.1/clipgrab.cpp
--- old/clipgrab-3.6.8/clipgrab.cpp 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/clipgrab.cpp 2018-10-03 08:13:44.000000000 +0200
@@ -565,11 +565,11 @@
portal = portals.at(i);
}
}
- emit compatiblePortalFound(found, portal);
+ emit compatiblePortalFound(found, url, portal);
}
else
{
- emit compatiblePortalFound(false, 0);
+ emit compatiblePortalFound(false, url, NULL);
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/clipgrab.h new/clipgrab-3.7.1/clipgrab.h
--- old/clipgrab-3.6.8/clipgrab.h 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/clipgrab.h 2018-10-03 08:13:44.000000000 +0200
@@ -143,7 +143,7 @@
void updateReadyRead();
signals:
- void compatiblePortalFound(bool, video* portal);
+ void compatiblePortalFound(bool, QString url, video* portal);
void compatibleUrlFoundInClipboard(QString url);
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/clipgrab.pro new/clipgrab-3.7.1/clipgrab.pro
--- old/clipgrab-3.6.8/clipgrab.pro 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/clipgrab.pro 2018-10-03 08:13:44.000000000 +0200
@@ -94,5 +94,5 @@
OBJECTIVE_SOURCES += savedialog_mac.mm
LIBS += -framework AppKit -framework Foundation
}
-VERSION = 3.6.8
+VERSION = 3.7.1
DEFINES += CLIPGRAB_VERSION=$$VERSION
Binary files old/clipgrab-3.6.8/clipgrab_fi.qm and new/clipgrab-3.7.1/clipgrab_fi.qm differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/clipgrab_fi.ts new/clipgrab-3.7.1/clipgrab_fi.ts
--- old/clipgrab-3.6.8/clipgrab_fi.ts 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/clipgrab_fi.ts 2018-10-03 08:13:44.000000000 +0200
@@ -150,7 +150,7 @@
<message>
<location filename="mainwindow.cpp" line="603"/>
<source>ClipGrab has finished downloading and converting all selected videos.</source>
- <translation>ClipGrab on ladannut ja muunanut valitut videot.</translation>
+ <translation>ClipGrab on ladannut ja muuntanut valitut videot.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="668"/>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/mainwindow.cpp new/clipgrab-3.7.1/mainwindow.cpp
--- old/clipgrab-3.6.8/mainwindow.cpp 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/mainwindow.cpp 2018-10-03 08:13:44.000000000 +0200
@@ -54,7 +54,7 @@
//*
//* Clipboard Handling
//*
- connect(cg, SIGNAL(compatiblePortalFound(bool, video*)), this, SLOT(compatiblePortalFound(bool, video*)));
+ connect(cg, SIGNAL(compatiblePortalFound(bool, QString, video*)), this, SLOT(compatiblePortalFound(bool, QString, video*)));
connect(cg, SIGNAL(compatibleUrlFoundInClipboard(QString)), this, SLOT(compatibleUrlFoundInClipBoard(QString)));
//*
@@ -85,9 +85,10 @@
//* Search Tab
//*
this->ui.searchWebView->setContextMenuPolicy(Qt::NoContextMenu);
-
this->searchNam = new QNetworkAccessManager();
+ connect(ui.searchLineEdit, SIGNAL(textChanged(QString)), cg, SLOT(determinePortal(QString)));
+
//*
//* Settings Tab
//*
@@ -317,7 +318,7 @@
}
}
-void MainWindow::compatiblePortalFound(bool found, video* portal)
+void MainWindow::compatiblePortalFound(bool found, QString url, video* portal)
{
disableDownloadUi(true);
this->updatingComboQuality = true;
@@ -325,6 +326,8 @@
this->updatingComboQuality = false;
if (found == true)
{
+ this->ui.mainTab->setCurrentIndex(1);
+ ui.downloadLineEdit->setText(url);
ui.downloadLineEdit->setReadOnly(true);
ui.downloadInfoBox->setText(tr("Please wait while ClipGrab is loading information about the video ..."));
@@ -743,7 +746,7 @@
searchReply->abort();
searchReply->deleteLater();
}
- this->searchReply = searchNam->get(QNetworkRequest(QUrl("https://www.youtube.com/results?search_query==" + keywords.replace(QRegExp("[&\\?%\\s]"), "+"))));
+ this->searchReply = searchNam->get(QNetworkRequest(QUrl("https://www.youtube.com/results?search_query=" + keywords.replace(QRegExp("[&\\?%\\s]"), "+"))));
connect(this->searchReply, SIGNAL(finished()), this, SLOT(processSearchReply()));
}
else
@@ -761,15 +764,14 @@
page->deleteLater();
QWebElementCollection entries = page->mainFrame()->findAllElements(".yt-lockup");
- int limit = 12;
- if (searchReply->url().toString() == "https://www.youtube.com") {
- limit = 4;
- }
-
QString searchHtml;
searchHtml.append("<style>body {margin:0;padding:0;width:100%;left:0px;top:0px;font-family:'Segoe UI', Ubuntu, sans-serif} img{position:relative;top:-22px;left:-15px} .entry{display:block;position:relative;width:50%;float:left;height:100px;} a{color:#1a1a1a;text-decoration:none;} span.title{display:block;font-weight:bold;font-size:14px;position:absolute;left:140px;top:16px;} span.duration{display:block;font-size:11px;position:absolute;left:140px;top:70px;color:#aaa} span.thumbnail{width:120px;height:68px;background:#00b2de;display:block;overflow:hidden;position:absolute;left:8px;top:16px;} a:hover{background: #00b2de;color:#fff}</style>");
searchHtml.append("<body>");
+ int limit = -1;
+ if (searchReply->url().toString() == "https://www.youtube.com") {
+ limit = 4;
+ }
int i=0;
foreach (QWebElement entry, entries)
{
@@ -796,7 +798,7 @@
searchHtml.append("</a>");
i++;
- if (i == limit) {
+ if (limit > 0 && i == limit) {
break;
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/mainwindow.h new/clipgrab-3.7.1/mainwindow.h
--- old/clipgrab-3.6.8/mainwindow.h 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/mainwindow.h 2018-10-03 08:13:44.000000000 +0200
@@ -51,7 +51,7 @@
public slots:
void startDownload();
- void compatiblePortalFound(bool, video*);
+ void compatiblePortalFound(bool, QString, video*);
void compatibleUrlFoundInClipBoard(QString url);
void updateVideoInfo();
void targetFileSelected(QString target);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/video_dailymotion.cpp new/clipgrab-3.7.1/video_dailymotion.cpp
--- old/clipgrab-3.6.8/video_dailymotion.cpp 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/video_dailymotion.cpp 2018-10-03 08:13:44.000000000 +0200
@@ -31,8 +31,8 @@
this->_supportsThumbnail = true;
this->_supportsSearch = true;
this->_icon = 0;
- this->_urlRegExp << QRegExp("http[s]?://\\w*\\.dailymotion\\.com/video/.*", Qt::CaseInsensitive);
- this->_urlRegExp << QRegExp("http[s]?://dai\\.ly/.*", Qt::CaseInsensitive);
+ this->_urlRegExp << QRegExp("http[s]?://\\w*\\.dailymotion\\.com/video/([^?/]+)", Qt::CaseInsensitive);
+ this->_urlRegExp << QRegExp("http[s]?://dai\\.ly/([^?/]+)", Qt::CaseInsensitive);
}
video* video_dailymotion::createNewInstance()
@@ -44,9 +44,15 @@
{
_originalUrl = url;
- if (_url.isEmpty())
+ for (uint i = 0; i < this->_urlRegExp.length(); i++)
{
- this->_url = QUrl(url);
+ if (this->_urlRegExp.at(i).indexIn((url)) == -1)
+ {
+ continue;
+ }
+
+ QString videoId = this->_urlRegExp.at(i).cap(1);
+ this->_url = QUrl("https://www.dailymotion.com/player/metadata/video/" + videoId);
QNetworkCookieJar* cookieJar = new QNetworkCookieJar;
QList<QNetworkCookie> cookieList;
@@ -54,57 +60,36 @@
cookieJar->setCookiesFromUrl(cookieList, _url);
this->handler->networkAccessManager->setCookieJar(cookieJar);
- return _url.isValid();
- }
- else
- {
- return false;
+ return true;
}
+ return false;
}
-void video_dailymotion::parseVideo(QString html)
+void video_dailymotion::parseVideo(QString json)
{
- QRegExp expression;
- expression = QRegExp("\"og:title\" content=\"(.*)\"");
- expression.setMinimal(true);
- if (expression.indexIn(html) !=-1)
- {
-
- _title = QString(expression.cap(1));
- _title = _title.replace(QRegExp("- Dailymotion$"), "");
+ _title = this->getProperty(json, "title");
- html = QUrl::fromEncoded(html.toAscii()).toString(QUrl::None);
- expression = QRegExp("var __PLAYER_CONFIG__\\s*=\\s*(\\{.+\\});");
- expression.setMinimal(true);
+ QList<dailymotion_quality> qualities;
+ qualities << dailymotion_quality("1080", tr("HD (1080p)"));
+ qualities << dailymotion_quality("720", tr("HD (720p)"));
+ qualities << dailymotion_quality("480", tr("480p"));
+ qualities << dailymotion_quality("380", tr("380p"));
+ qualities << dailymotion_quality("240", tr("240p"));
- if (expression.indexIn(html)!=-1)
+ QListIterator<dailymotion_quality> i(qualities);
+ while (i.hasNext())
+ {
+ dailymotion_quality quality = i.next();
+ QString url = getQualityUrl(json, quality.key);
+ if (!url.isEmpty())
{
- QString json = expression.cap(1);
-
- QList<dailymotion_quality> qualities;
- qualities << dailymotion_quality("1080", tr("HD (1080p)"));
- qualities << dailymotion_quality("720", tr("HD (720p)"));
- qualities << dailymotion_quality("480", tr("480p"));
- qualities << dailymotion_quality("380", tr("380p"));
- qualities << dailymotion_quality("240", tr("240p"));
-
- QListIterator<dailymotion_quality> i(qualities);
- while (i.hasNext())
- {
- dailymotion_quality quality = i.next();
- QString url = getQualityUrl(json, quality.key);
- if (!url.isEmpty())
- {
- videoQuality newQuality;
- newQuality.quality = quality.name;
- newQuality.videoUrl = url;
- newQuality.containerName = url.contains(".mp4") ? ".mp4" : ".flv";
- newQuality.resolution = quality.key.toInt();
- _supportedQualities.append(newQuality);
- }
- }
+ videoQuality newQuality;
+ newQuality.quality = quality.name;
+ newQuality.videoUrl = url;
+ newQuality.containerName = url.contains(".mp4") ? ".mp4" : ".flv";
+ newQuality.resolution = quality.key.toInt();
+ _supportedQualities.append(newQuality);
}
-
}
if (_supportedQualities.isEmpty() | _title.isEmpty())
@@ -115,13 +100,29 @@
emit analysingFinished();
}
+QString video_dailymotion::getProperty(QString json, QString property) {
+ QWebView* view = new QWebView();
+ QString script;
+
+ script.append( "function getProperty(property) {\n");
+ script.append( " var json = " + json + ";\n");
+ script.append( " return json[property];\n");
+ script.append( "}\n");
+ view->setHtml("<script>" + script + "</script>");
+ QString result = view->page()->mainFrame()->evaluateJavaScript("getProperty(\"" + property +"\")").toString();
+
+ view->deleteLater();
+
+ return result;
+}
+
QString video_dailymotion::getQualityUrl(QString json, QString quality)
{
QWebView* view = new QWebView();
QString script;
script.append( "function getUrl() {\n");
script.append( " var json = " + json + ";\n");
- script.append( " var sources = json.metadata.qualities['" + quality + "'];\n");
+ script.append( " var sources = json.qualities['" + quality + "'];\n");
script.append( " for (var i in sources) {\n");
script.append( " if (sources[i].type == 'video\\/mp4') {\n");
script.append( " return sources[i].url\n");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/video_dailymotion.h new/clipgrab-3.7.1/video_dailymotion.h
--- old/clipgrab-3.6.8/video_dailymotion.h 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/video_dailymotion.h 2018-10-03 08:13:44.000000000 +0200
@@ -45,9 +45,12 @@
public:
video_dailymotion();
video* createNewInstance();
- QString getQualityUrl(QString json, QString quality);
bool setUrl(QString);
+ private:
+ QString getQualityUrl(QString json, QString quality);
+ QString getProperty(QString json, QString property);
+
public slots:
virtual void parseVideo(QString html);
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/video_facebook.cpp new/clipgrab-3.7.1/video_facebook.cpp
--- old/clipgrab-3.6.8/video_facebook.cpp 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/video_facebook.cpp 2018-10-03 08:13:44.000000000 +0200
@@ -73,11 +73,34 @@
QSettings settings;
QRegExp expression;
- expression = QRegExp("\"?videoData\"?:(\\[\\{.*\\}\\])");
+ //Fetch title
+ expression = QRegExp("<meta property=\"og:title\" content=\"(.*)\" />");
expression.setMinimal(true);
+ if (expression.indexIn(data) > -1)
+ {
+ this->_title = expression.cap(1);
+ }
+ expression = QRegExp("<title id=\"pageTitle\">(.*)</title>");
+ expression.setMinimal(true);
+ if ((this->_title.isEmpty() || this->_title.startsWith("Facebook") || this->_title.startsWith("Log In")) && expression.indexIn(data) > -1)
+ {
+ this->_title = expression.cap(1);
+ }
+
+ //Fetch userID and videoData
+ expression = QRegExp("\"USER_ID\":\"(\\d+)\"");
+ QString userID;
+ if (expression.indexIn(data) > -1)
+ {
+ userID = expression.cap(1);
+ }
+ expression = QRegExp("(\"videoData\":)|videoData:\\[\\{");
+ expression.setMinimal(true);
+ bool hasVideoData = (expression.indexIn(data) > -1);
- //If there is no video data, login might be required
- if (expression.indexIn(data) == -1) {
+ //Determine if login or fetching player is required
+ if (userID == "0" && !hasVideoData)
+ {
if (this->authenticating)
{
//If we’re already in the process of authenticating
@@ -88,7 +111,7 @@
dui = new Ui::LoginDialog();
passwordDialog = new QDialog;
dui->setupUi(passwordDialog);
- connect(dui->loginDialogWebView, SIGNAL(loadFinished(bool)), this, SLOT(handleLogin()));
+ connect(dui->loginDialogWebView, SIGNAL(loadProgress(int)), this, SLOT(handleLogin()));
connect(this, SIGNAL(analysingFinished()), this, SLOT(acceptLoginDialog()));
dui->loginDialogWebView->setUrl(QUrl::fromUserInput("https://m.facebook.com/login.php?next=" + QUrl::toPercentEncoding(this->_url.toString())));
dui->rememberLogin->setChecked(settings.value("facebookRememberLogin", true).toBool());
@@ -99,14 +122,46 @@
return;
}
+ disconnect(this, SIGNAL(analysingFinished()), this, SLOT(acceptLoginDialog()));
passwordDialog->deleteLater();
emit error("Could not retrieve video info.", this);
emit analysingFinished();
return;
}
+ else if (userID != "0" && !hasVideoData)
+ {
+ QRegExp videoIDRegExp = QRegExp("videos/(\\d+)");
+
+ QString dtsg;
+ QRegExp dtsgRegExp("name=\"fb_dtsg\" value=\"([^\"]+)\"");
+ if (dtsgRegExp.indexIn(data) > -1)
+ {
+ dtsg = dtsgRegExp.cap(1);
+ }
+ dtsgRegExp = QRegExp("\\[\"DTSGInitialData\",\\[\\],\\{\"token\":\"([^\"]+)\"");
+ if (dtsgRegExp.indexIn(data) > -1)
+ {
+ dtsg = dtsgRegExp.cap(1);
+ }
+
+ if (videoIDRegExp.indexIn(this->_url.toString()) == -1 || dtsg.isEmpty())
+ {
+ emit analysingFinished();
+ return;
+ }
+
+ QString playerLink = "https://www.facebook.com/video/tahoe/async/" + videoIDRegExp.cap(1) + "/?payloadtype=primary";
+
+ QUrl postData;
+ postData.addQueryItem("__a", "1");
+ postData.addQueryItem("__user", userID);
+ postData.addQueryItem("fb_dtsg", dtsg);
+
+ qDebug() << "Downloading player ..." << playerLink << postData.encodedQuery();
+ handler->addDownload(playerLink, false, postData.encodedQuery());
+ return;
+ }
- //Parse video information
- QString videoData = expression.cap(1);
QList< QPair<QRegExp, QString> > supportedQualities;
supportedQualities.append(qMakePair(QRegExp("\"?hd_src_no_ratelimit\"?:\"([^\"]+)"), tr("HD")));
supportedQualities.append(qMakePair(QRegExp("\"?hd_src\"?:\"([^\"]+)"), tr("HD")));
@@ -131,7 +186,7 @@
continue;
}
- if (expression.indexIn(videoData) == -1)
+ if (expression.indexIn(data) == -1)
{
continue;
}
@@ -148,24 +203,28 @@
this->_supportedQualities.append(newQuality);
}
- //Obtain page title
- expression = QRegExp("<title.*>(.*)</title>");
- expression.setMinimal(true);
- if (expression.indexIn(data) == -1)
- {
- emit error("Could not retrieve video title.", this);
+
+ if (!this->authenticating || (!this->_supportedQualities.isEmpty() && !this->_title.isEmpty())) {
emit analysingFinished();
- return;
+ } else {
+ emit error("Could not retrieve video info.", this);
}
- this->_title = expression.cap(1);
-
- emit analysingFinished();
}
void video_facebook::handleLogin()
{
QString html = dui->loginDialogWebView->page()->mainFrame()->toHtml();
- this->parseVideo(html);
+ QRegExp userRegexp("\"USER_ID\":\"(\\d+)\"");
+ QRegExp dtsgRegexp("\\[\"DTSGInitialData\",\\[\\],\\{\"token\":\"([^\"]+)\"");
+
+ if (dtsgRegexp.indexIn((html)) == -1 || userRegexp.indexIn(html) == -1 || userRegexp.cap(1) == "0") {
+ return;
+ } else {
+ disconnect(dui->loginDialogWebView, SIGNAL(loadProgress(int)), this, SLOT(handleLogin()));
+ QList<QNetworkCookie> cookies = dui->loginDialogWebView->page()->networkAccessManager()->cookieJar()->cookiesForUrl(_url);
+ handler->networkAccessManager->cookieJar()->setCookiesFromUrl(cookies, _url);
+ parseVideo(html);
+ }
}
void video_facebook::acceptLoginDialog()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/video_youtube.cpp new/clipgrab-3.7.1/video_youtube.cpp
--- old/clipgrab-3.6.8/video_youtube.cpp 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/video_youtube.cpp 2018-10-03 08:13:44.000000000 +0200
@@ -222,9 +222,18 @@
QRegExp expression("signature=|set\\(\"signature\",|set\\([\\w\\.]+\\|\\|\"signature\",([$\\w]+)\\(");
expression.setMinimal(true);
- if (expression.indexIn(js) != -1)
- {
+
+ if (expression.indexIn(js) > -1) {
methodName = expression.cap(1);
+ } else {
+ expression = QRegExp("([$\\w]+)\\s*=\\s*function\\(([$\\w]+)\\)\\{\\2=\\2\\.split\\(\"\"\\)");
+ expression.setMinimal(true);
+ if (expression.indexIn(js) != -1) {
+ methodName = expression.cap(1);
+ }
+ }
+
+ if (!methodName.isEmpty()) {
this->signatureMethodName = methodName;
extractJSMethod(methodName, js);
}
@@ -285,6 +294,8 @@
dui = new Ui::LoginDialog();
passwordDialog = new QDialog;
dui->setupUi(passwordDialog);
+ disconnect(dui->buttonBox, SIGNAL(rejected()), passwordDialog, SLOT(reject()));
+ connect(dui->buttonBox, SIGNAL(rejected()), this, SLOT(handleLoginDialogRejected()));
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
dui->loginDialogWebView->settings()->setAttribute(QWebSettings::JavascriptEnabled, false);
#endif
@@ -729,3 +740,10 @@
{
dui->loginDialogWebView->history()->clear();
}
+
+void video_youtube::handleLoginDialogRejected() {
+ if (QApplication::focusWidget() == dui->loginDialogWebView) {
+ return;
+ }
+ passwordDialog->reject();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/clipgrab-3.6.8/video_youtube.h new/clipgrab-3.7.1/video_youtube.h
--- old/clipgrab-3.6.8/video_youtube.h 2018-02-19 13:15:43.000000000 +0100
+++ new/clipgrab-3.7.1/video_youtube.h 2018-10-03 08:13:44.000000000 +0200
@@ -96,6 +96,7 @@
public slots:
void handleLoginUrlChanged(const QUrl);
void handleLoginLoadFinished();
+ void handleLoginDialogRejected();
};
#endif // video_YOUTUBE_H
++++++ clipgrab-qt5.patch ++++++
--- /var/tmp/diff_new_pack.XGhxVd/_old 2018-10-29 14:58:57.834024023 +0100
+++ /var/tmp/diff_new_pack.XGhxVd/_new 2018-10-29 14:58:57.834024023 +0100
@@ -10,58 +10,14 @@
from the https://github.com/OpenHelios/clipgrab-qt5
fork in order to use Qt5 libraries instead.
----
- .gitignore | 10 ++++++++--
- clipgrab.cpp | 18 +++++++++++++++++-
- clipgrab.h | 4 ++++
- clipgrab.pro | 26 +++++++++++++++-----------
- http_handler.cpp | 28 ++++++++++++++++++++++++++++
- main.cpp | 29 +++++++++++++++++++++++------
- mainwindow.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
- mainwindow.h | 10 +++++++++-
- message_dialog.h | 7 ++++++-
- notifications.h | 5 +++++
- video.cpp | 4 ++++
- video.h | 4 ++++
- video_dailymotion.cpp | 7 +++++++
- video_dailymotion.h | 3 ++-
- video_facebook.cpp | 3 +++
- video_facebook.h | 2 +-
- video_heuristic.cpp | 8 ++++++++
- video_vimeo.h | 11 ++++++++---
- video_youtube.cpp | 12 ++++++++++++
- video_youtube.h | 14 +++++++++-----
- 20 files changed, 221 insertions(+), 33 deletions(-)
+2018-10-27 20:20:48 +0200
+Patch updates for version 3.7.1 courtesy of "kikadf"
+from the Arch AUR project.
-Index: clipgrab-3.6.8/.gitignore
-===================================================================
---- clipgrab-3.6.8.orig/.gitignore
-+++ clipgrab-3.6.8/.gitignore
-@@ -1,12 +1,18 @@
-+/debug/
-+/release/
- *~
- .DS_Store
--clipgrab.pro.user
-+clipgrab.pro.user*
- ClipGrab.app
- ui_*.h
- Makefile
--*.o
-+Makefile.Debug
-+Makefile.Release
- moc_*.cpp
- *.autosave
- qrc_resources.cpp
- build
- ClipGrab.xcodeproj
-+.qmake.stash
-+clipgrab
-+moc_predefs.h
-Index: clipgrab-3.6.8/clipgrab.cpp
-===================================================================
---- clipgrab-3.6.8.orig/clipgrab.cpp
-+++ clipgrab-3.6.8/clipgrab.cpp
+---
+diff -udp clipgrab-3.7.1.orig/clipgrab.cpp clipgrab-3.7.1/clipgrab.cpp
+--- clipgrab-3.7.1.orig/clipgrab.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/clipgrab.cpp 2018-10-27 20:16:12.351022193 +0200
@@ -23,6 +23,13 @@
#include "clipgrab.h"
@@ -103,10 +59,9 @@
QNetworkAccessManager* updateInfoNAM = new QNetworkAccessManager;
updateInfoNAM->get(updateInfoRequest);
connect(updateInfoNAM, SIGNAL(finished(QNetworkReply*)), this, SLOT(parseUpdateInfo(QNetworkReply*)));
-Index: clipgrab-3.6.8/clipgrab.h
-===================================================================
---- clipgrab-3.6.8.orig/clipgrab.h
-+++ clipgrab-3.6.8/clipgrab.h
+diff -udp clipgrab-3.7.1.orig/clipgrab.h clipgrab-3.7.1/clipgrab.h
+--- clipgrab-3.7.1.orig/clipgrab.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/clipgrab.h 2018-10-27 20:16:12.351022193 +0200
@@ -29,6 +29,10 @@
#include <QtXml>
#include <QtDebug>
@@ -118,10 +73,9 @@
#include "video.h"
#include "video_youtube.h"
#include "video_vimeo.h"
-Index: clipgrab-3.6.8/clipgrab.pro
-===================================================================
---- clipgrab-3.6.8.orig/clipgrab.pro
-+++ clipgrab-3.6.8/clipgrab.pro
+diff -udp clipgrab-3.7.1.orig/clipgrab.pro clipgrab-3.7.1/clipgrab.pro
+--- clipgrab-3.7.1.orig/clipgrab.pro 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/clipgrab.pro 2018-10-27 20:16:12.351022193 +0200
@@ -1,16 +1,24 @@
# #####################################################################
# Automatically generated by qmake (2.01a) Mo 26. Okt 18:26:00 2009
@@ -173,10 +127,9 @@
CODECFORTR = UTF-8
win32:RC_FILE = windows_icon.rc
macx {
-Index: clipgrab-3.6.8/http_handler.cpp
-===================================================================
---- clipgrab-3.6.8.orig/http_handler.cpp
-+++ clipgrab-3.6.8/http_handler.cpp
+diff -udp clipgrab-3.7.1.orig/http_handler.cpp clipgrab-3.7.1/http_handler.cpp
+--- clipgrab-3.7.1.orig/http_handler.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/http_handler.cpp 2018-10-27 20:16:12.351022193 +0200
@@ -45,14 +45,22 @@ QNetworkRequest http_handler::createRequ
QNetworkReply* http_handler::addDownload(QString url, bool chunked, QByteArray postData, QStringList segments)
{
@@ -253,10 +206,9 @@
for (int j = 0; j < parsedCookies.length(); j++)
{
cookies.append(parsedCookies.at(j));
-Index: clipgrab-3.6.8/main.cpp
-===================================================================
---- clipgrab-3.6.8.orig/main.cpp
-+++ clipgrab-3.6.8/main.cpp
+diff -udp clipgrab-3.7.1.orig/main.cpp clipgrab-3.7.1/main.cpp
+--- clipgrab-3.7.1.orig/main.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/main.cpp 2018-10-27 20:16:12.351022193 +0200
@@ -19,9 +19,14 @@
along with ClipGrab. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -310,10 +262,9 @@
cg.getUpdateInfo();
return app.exec();
}
-Index: clipgrab-3.6.8/mainwindow.cpp
-===================================================================
---- clipgrab-3.6.8.orig/mainwindow.cpp
-+++ clipgrab-3.6.8/mainwindow.cpp
+diff -udp clipgrab-3.7.1.orig/mainwindow.cpp clipgrab-3.7.1/mainwindow.cpp
+--- clipgrab-3.7.1.orig/mainwindow.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/mainwindow.cpp 2018-10-27 20:16:12.351022193 +0200
@@ -23,7 +23,23 @@
#include "mainwindow.h"
@@ -369,7 +320,7 @@
ui.downloadLineEdit->setFocus(Qt::OtherFocusReason);
int lastFormat = cg->settings.value("LastFormat", 0).toInt();
-@@ -99,7 +128,11 @@ void MainWindow::init()
+@@ -100,7 +129,11 @@ void MainWindow::init()
connect(this->ui.settingsRadioNotificationsNever, SIGNAL(toggled(bool)), this, SLOT(settingsNotifications_toggled(bool)));
@@ -381,7 +332,7 @@
this->ui.settingsSaveLastPath->setChecked(cg->settings.value("saveLastPath", true).toBool());
ui.settingsNeverAskForPath->setChecked(cg->settings.value("NeverAskForPath", false).toBool());
-@@ -238,7 +271,11 @@ void MainWindow::init()
+@@ -239,7 +272,11 @@ void MainWindow::init()
void MainWindow::startDownload()
{
@@ -393,7 +344,7 @@
QString fileName = currentVideo->getSaveTitle();
if (cg->settings.value("NeverAskForPath", false).toBool() == false)
-@@ -563,6 +600,7 @@ void MainWindow::on_settingsNeverAskForP
+@@ -566,6 +603,7 @@ void MainWindow::on_settingsNeverAskForP
if (exitBox->exec() == QMessageBox::Yes)
{
cg->cancelAll();
@@ -401,7 +352,7 @@
event->accept();
}
else
-@@ -572,6 +610,7 @@ void MainWindow::on_settingsNeverAskForP
+@@ -575,6 +613,7 @@ void MainWindow::on_settingsNeverAskForP
}
else
{
@@ -409,7 +360,7 @@
event->accept();;
}
}
-@@ -665,9 +704,17 @@ void MainWindow::timerEvent(QTimerEvent
+@@ -668,9 +707,17 @@ void MainWindow::timerEvent(QTimerEvent
if (downloadProgress.first != 0 && downloadProgress.second != 0)
{
#ifdef Q_WS_X11
@@ -427,10 +378,9 @@
#endif
setWindowTitle("ClipGrab - " + QString::number(downloadProgress.first*100/downloadProgress.second) + " %");
}
-Index: clipgrab-3.6.8/mainwindow.h
-===================================================================
---- clipgrab-3.6.8.orig/mainwindow.h
-+++ clipgrab-3.6.8/mainwindow.h
+diff -udp clipgrab-3.7.1.orig/mainwindow.h clipgrab-3.7.1/mainwindow.h
+--- clipgrab-3.7.1.orig/mainwindow.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/mainwindow.h 2018-10-27 20:16:12.351022193 +0200
@@ -24,10 +24,14 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
@@ -459,10 +409,9 @@
~MainWindow();
void init();
-Index: clipgrab-3.6.8/message_dialog.h
-===================================================================
---- clipgrab-3.6.8.orig/message_dialog.h
-+++ clipgrab-3.6.8/message_dialog.h
+diff -udp clipgrab-3.7.1.orig/message_dialog.h clipgrab-3.7.1/message_dialog.h
+--- clipgrab-3.7.1.orig/message_dialog.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/message_dialog.h 2018-10-27 20:16:12.351022193 +0200
@@ -1,9 +1,14 @@
#ifndef MESSAGE_DIALOG_H
#define MESSAGE_DIALOG_H
@@ -479,10 +428,9 @@
namespace Ui {
class messageDialog;
-Index: clipgrab-3.6.8/notifications.h
-===================================================================
---- clipgrab-3.6.8.orig/notifications.h
-+++ clipgrab-3.6.8/notifications.h
+diff -udp clipgrab-3.7.1.orig/notifications.h clipgrab-3.7.1/notifications.h
+--- clipgrab-3.7.1.orig/notifications.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/notifications.h 2018-10-27 20:16:12.351022193 +0200
@@ -25,6 +25,11 @@
#define FOO_H
@@ -495,10 +443,9 @@
#ifdef Q_WS_MAC64
#include "notifications_mac.h"
-Index: clipgrab-3.6.8/video.cpp
-===================================================================
---- clipgrab-3.6.8.orig/video.cpp
-+++ clipgrab-3.6.8/video.cpp
+diff -udp clipgrab-3.7.1.orig/video.cpp clipgrab-3.7.1/video.cpp
+--- clipgrab-3.7.1.orig/video.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video.cpp 2018-10-27 20:16:12.355021553 +0200
@@ -195,7 +195,11 @@ void video::changeProgress(qint64 bytesR
this->_progressBar->setFormat("%p%");
this->_progressBar->setMaximum(bytesTotal);
@@ -511,25 +458,9 @@
}
}
else
-Index: clipgrab-3.6.8/video.h
-===================================================================
---- clipgrab-3.6.8.orig/video.h
-+++ clipgrab-3.6.8/video.h
-@@ -26,6 +26,10 @@
-
- #include <QtGui>
- #include <QtNetwork>
-+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
-+#include <QtWidgets/QTreeWidgetItem>
-+#include <QtWidgets/QProgressBar>
-+#endif
- #include "converter.h"
- #include "converter_ffmpeg.h"
- #include "http_handler.h"
-Index: clipgrab-3.6.8/video_dailymotion.cpp
-===================================================================
---- clipgrab-3.6.8.orig/video_dailymotion.cpp
-+++ clipgrab-3.6.8/video_dailymotion.cpp
+diff -udp clipgrab-3.7.1.orig/video_dailymotion.cpp clipgrab-3.7.1/video_dailymotion.cpp
+--- clipgrab-3.7.1.orig/video_dailymotion.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_dailymotion.cpp 2018-10-27 20:16:12.351022193 +0200
@@ -22,6 +22,9 @@
@@ -540,19 +471,9 @@
video_dailymotion::video_dailymotion()
{
-@@ -73,7 +76,7 @@ void video_dailymotion::parseVideo(QStri
- _title = QString(expression.cap(1));
- _title = _title.replace(QRegExp("- Dailymotion$"), "");
-
-- html = QUrl::fromEncoded(html.toAscii()).toString(QUrl::None);
-+ html = QUrl::fromEncoded(html.toLatin1()).toString(QUrl::None);
- expression = QRegExp("var __PLAYER_CONFIG__\\s*=\\s*(\\{.+\\});");
- expression.setMinimal(true);
-
-Index: clipgrab-3.6.8/video_dailymotion.h
-===================================================================
---- clipgrab-3.6.8.orig/video_dailymotion.h
-+++ clipgrab-3.6.8/video_dailymotion.h
+diff -udp clipgrab-3.7.1.orig/video_dailymotion.h clipgrab-3.7.1/video_dailymotion.h
+--- clipgrab-3.7.1.orig/video_dailymotion.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_dailymotion.h 2018-10-27 20:16:12.351022193 +0200
@@ -23,8 +23,9 @@
#ifndef VIDEO_DAILYMOTION_H
@@ -564,24 +485,47 @@
struct dailymotion_quality
{
-Index: clipgrab-3.6.8/video_facebook.cpp
-===================================================================
---- clipgrab-3.6.8.orig/video_facebook.cpp
-+++ clipgrab-3.6.8/video_facebook.cpp
-@@ -22,6 +22,9 @@
+diff -udp clipgrab-3.7.1.orig/video_facebook.cpp clipgrab-3.7.1/video_facebook.cpp
+--- clipgrab-3.7.1.orig/video_facebook.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_facebook.cpp 2018-10-27 20:16:12.351022193 +0200
+@@ -22,6 +22,10 @@
#include "video_facebook.h"
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+ #include <QtWebKitWidgets/QtWebKitWidgets>
++ #include <QUrlQuery>
+#endif
video_facebook::video_facebook()
{
-Index: clipgrab-3.6.8/video_facebook.h
-===================================================================
---- clipgrab-3.6.8.orig/video_facebook.h
-+++ clipgrab-3.6.8/video_facebook.h
+@@ -152,6 +156,7 @@ void video_facebook::parseVideo(QString
+
+ QString playerLink = "https://www.facebook.com/video/tahoe/async/" + videoIDRegExp.cap(1) + "/?payloadtype=primary";
+
++#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+ QUrl postData;
+ postData.addQueryItem("__a", "1");
+ postData.addQueryItem("__user", userID);
+@@ -159,6 +164,15 @@ void video_facebook::parseVideo(QString
+
+ qDebug() << "Downloading player ..." << playerLink << postData.encodedQuery();
+ handler->addDownload(playerLink, false, postData.encodedQuery());
++#else
++ QUrlQuery postData;
++ postData.addQueryItem("__a", "1");
++ postData.addQueryItem("__user", userID);
++ postData.addQueryItem("fb_dtsg", dtsg);
++
++ qDebug() << "Downloading player ..." << playerLink << postData.query(QUrl::FullyEncoded).toUtf8();
++ handler->addDownload(playerLink, false, postData.query(QUrl::FullyEncoded).toUtf8());
++#endif
+ return;
+ }
+
+diff -udp clipgrab-3.7.1.orig/video_facebook.h clipgrab-3.7.1/video_facebook.h
+--- clipgrab-3.7.1.orig/video_facebook.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_facebook.h 2018-10-27 20:16:12.355021553 +0200
@@ -24,9 +24,9 @@
#ifndef VIDEO_FACEBOOK_H
#define VIDEO_FACEBOOK_H
@@ -593,10 +537,23 @@
class video_facebook : public video
{
-Index: clipgrab-3.6.8/video_heuristic.cpp
-===================================================================
---- clipgrab-3.6.8.orig/video_heuristic.cpp
-+++ clipgrab-3.6.8/video_heuristic.cpp
+diff -udp clipgrab-3.7.1.orig/video.h clipgrab-3.7.1/video.h
+--- clipgrab-3.7.1.orig/video.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video.h 2018-10-27 20:16:12.355021553 +0200
+@@ -26,6 +26,10 @@
+
+ #include <QtGui>
+ #include <QtNetwork>
++#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
++#include <QtWidgets/QTreeWidgetItem>
++#include <QtWidgets/QProgressBar>
++#endif
+ #include "converter.h"
+ #include "converter_ffmpeg.h"
+ #include "http_handler.h"
+diff -udp clipgrab-3.7.1.orig/video_heuristic.cpp clipgrab-3.7.1/video_heuristic.cpp
+--- clipgrab-3.7.1.orig/video_heuristic.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_heuristic.cpp 2018-10-27 20:16:12.355021553 +0200
@@ -124,7 +124,11 @@ void video_heuristic::parseVideo(QString
{
videoQuality newQuality;
@@ -621,10 +578,9 @@
newQuality.quality = tr("normal");
_supportedQualities.append(newQuality);
emit analysingFinished();
-Index: clipgrab-3.6.8/video_vimeo.h
-===================================================================
---- clipgrab-3.6.8.orig/video_vimeo.h
-+++ clipgrab-3.6.8/video_vimeo.h
+diff -udp clipgrab-3.7.1.orig/video_vimeo.h clipgrab-3.7.1/video_vimeo.h
+--- clipgrab-3.7.1.orig/video_vimeo.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_vimeo.h 2018-10-27 20:16:12.355021553 +0200
@@ -24,10 +24,15 @@
#ifndef video_vimeo_H
#define video_vimeo_H
@@ -644,10 +600,9 @@
#include "ui_login_dialog.h"
class video_vimeo : public video
-Index: clipgrab-3.6.8/video_youtube.cpp
-===================================================================
---- clipgrab-3.6.8.orig/video_youtube.cpp
-+++ clipgrab-3.6.8/video_youtube.cpp
+diff -udp clipgrab-3.7.1.orig/video_youtube.cpp clipgrab-3.7.1/video_youtube.cpp
+--- clipgrab-3.7.1.orig/video_youtube.cpp 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_youtube.cpp 2018-10-27 20:16:12.355021553 +0200
@@ -22,7 +22,11 @@
@@ -672,7 +627,7 @@
QRegExp sigExpression;
sigExpression = QRegExp("(?:^|[^a-zA-Z])[,]?s(ig)?=([^,]+)");
-@@ -663,7 +671,11 @@ void video_youtube::parseVideo(QString h
+@@ -674,7 +682,11 @@ void video_youtube::parseVideo(QString h
{
videoQuality newQuality;
newQuality.quality = tr("normal");
@@ -684,10 +639,9 @@
_supportedQualities.append(newQuality);
}
else
-Index: clipgrab-3.6.8/video_youtube.h
-===================================================================
---- clipgrab-3.6.8.orig/video_youtube.h
-+++ clipgrab-3.6.8/video_youtube.h
+diff -udp clipgrab-3.7.1.orig/video_youtube.h clipgrab-3.7.1/video_youtube.h
+--- clipgrab-3.7.1.orig/video_youtube.h 2018-10-03 08:13:44.000000000 +0200
++++ clipgrab-3.7.1/video_youtube.h 2018-10-27 20:16:12.355021553 +0200
@@ -24,13 +24,17 @@
#ifndef video_YOUTUBE_H
#define video_YOUTUBE_H
1
0
Hello community,
here is the log from the commit of package gphoto for openSUSE:Factory checked in at 2018-10-29 14:22:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gphoto (Old)
and /work/SRC/openSUSE:Factory/.gphoto.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gphoto"
Mon Oct 29 14:22:40 2018 rev:47 rq:645041 version:2.5.20
Changes:
--------
--- /work/SRC/openSUSE:Factory/gphoto/gphoto.changes 2018-04-19 15:29:24.935234642 +0200
+++ /work/SRC/openSUSE:Factory/.gphoto.new/gphoto.changes 2018-10-29 14:58:55.466021067 +0100
@@ -1,0 +2,9 @@
+Sat Oct 27 16:24:50 UTC 2018 - meissner(a)suse.com
+
+- updated to 2.5.20 release
+ * maximum number in file ranges bumped from 16384 to 65536
+ * add shell commands to match commandline: summary, storage-info, trigger-capture
+ * fixed a fd leak
+ * translations: updated simplified chinese
+
+-------------------------------------------------------------------
Old:
----
gphoto2-2.5.17.tar.bz2
gphoto2-2.5.17.tar.bz2.asc
New:
----
gphoto2-2.5.20.tar.bz2
gphoto2-2.5.20.tar.bz2.asc
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ gphoto.spec ++++++
--- /var/tmp/diff_new_pack.92SLhP/_old 2018-10-29 14:58:56.046021802 +0100
+++ /var/tmp/diff_new_pack.92SLhP/_new 2018-10-29 14:58:56.050021807 +0100
@@ -27,7 +27,7 @@
Summary: A Digital Camera Utility
License: GPL-2.0+
Group: Hardware/Camera
-Version: 2.5.17
+Version: 2.5.20
Release: 0
Source0: https://downloads.sourceforge.net/project/gphoto/gphoto/%{version}/%{name}2…
Source1: https://downloads.sourceforge.net/project/gphoto/gphoto/%{version}/%{name}2…
++++++ gphoto2-2.5.17.tar.bz2 -> gphoto2-2.5.20.tar.bz2 ++++++
++++ 13000 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package apache-commons-jxpath for openSUSE:Factory checked in at 2018-10-29 14:22:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/apache-commons-jxpath (Old)
and /work/SRC/openSUSE:Factory/.apache-commons-jxpath.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "apache-commons-jxpath"
Mon Oct 29 14:22:35 2018 rev:6 rq:645028 version:1.3
Changes:
--------
--- /work/SRC/openSUSE:Factory/apache-commons-jxpath/apache-commons-jxpath.changes 2018-07-07 21:58:09.891335412 +0200
+++ /work/SRC/openSUSE:Factory/.apache-commons-jxpath.new/apache-commons-jxpath.changes 2018-10-29 14:58:54.866020304 +0100
@@ -1,0 +2,6 @@
+Sat Oct 20 13:03:03 UTC 2018 - Fridrich Strba <fstrba(a)suse.com>
+
+- Install the provided pom.xml file and generate the mvn(...)
+ provides
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ apache-commons-jxpath.spec ++++++
--- /var/tmp/diff_new_pack.8zBgmR/_old 2018-10-29 14:58:55.330020895 +0100
+++ /var/tmp/diff_new_pack.8zBgmR/_new 2018-10-29 14:58:55.334020900 +0100
@@ -12,7 +12,7 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
@@ -24,7 +24,7 @@
Summary: Simple XPath interpreter
License: Apache-2.0
Group: Development/Libraries/Java
-Url: http://commons.apache.org/%{base_name}/
+URL: http://commons.apache.org/%{base_name}/
Source0: http://www.apache.org/dist/commons/%{base_name}/source/%{short_name}-%{vers…
Source1: %{short_name}.depmap
Patch0: %{short_name}-mockrunner.patch
@@ -33,6 +33,7 @@
BuildRequires: apache-commons-beanutils
BuildRequires: el_api >= 3.0
BuildRequires: java-devel >= 1.8
+BuildRequires: javapackages-local
BuildRequires: javapackages-tools
BuildRequires: jdom
BuildRequires: jsp
@@ -80,9 +81,20 @@
done
popd # come back from javadir
+# pom
+install -d -m 755 %{buildroot}%{_mavenpomdir}/%{last_path_segment}/
+install -pm 644 pom.xml %{buildroot}%{_mavenpomdir}/%{name}-%{version}.pom
+%add_maven_depmap %{name}-%{version}.pom %{name}-%{version}.jar
+
%files
%defattr(0644,root,root,0755)
-%doc LICENSE.txt
+%license LICENSE.txt
%{_javadir}/*.jar
+%{_mavenpomdir}/*
+%if %{defined _maven_repository}
+%{_mavendepmapfragdir}/%{name}
+%else
+%{_datadir}/maven-metadata/%{name}.xml*
+%endif
%changelog
1
0
Hello community,
here is the log from the commit of package libfilezilla for openSUSE:Factory checked in at 2018-10-29 14:22:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libfilezilla (Old)
and /work/SRC/openSUSE:Factory/.libfilezilla.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libfilezilla"
Mon Oct 29 14:22:31 2018 rev:21 rq:645011 version:0.15.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/libfilezilla/libfilezilla.changes 2018-10-15 09:48:06.123059274 +0200
+++ /work/SRC/openSUSE:Factory/.libfilezilla.new/libfilezilla.changes 2018-10-29 14:58:52.738017542 +0100
@@ -1,0 +2,17 @@
+Sat Oct 27 08:35:12 UTC 2018 - ecsos(a)opensuse.org
+
+- update to 0.15.0
+ * New features:
+ - libfilezilla now depends on Nettle >= 3.1
+ - Added fz::sha512, fz::sha256, fz::sha1 and fz::md5 hash
+ functions
+ - Added fz::hash_accumulator
+ - Added fz::hmac_sha256 HMAC function
+ - Added asymmetric encryption scheme using X25519
+ - Added signature scheme using Ed25519
+ * Bugfixes and minor changes:
+ - Changed and documented semantics of the return value of
+ fz::remove_file, removing a non-existing file is not an error
+- Drop extra COPYING file and use it from upstream
+
+-------------------------------------------------------------------
Old:
----
COPYING
libfilezilla-0.14.0.tar.bz2
New:
----
libfilezilla-0.15.0.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ libfilezilla.spec ++++++
--- /var/tmp/diff_new_pack.ZNyW9V/_old 2018-10-29 14:58:53.326018313 +0100
+++ /var/tmp/diff_new_pack.ZNyW9V/_new 2018-10-29 14:58:53.330018318 +0100
@@ -20,14 +20,13 @@
%define libname %{name}%{major}
%define develname %{name}-devel
Name: libfilezilla
-Version: 0.14.0
+Version: 0.15.0
Release: 0
Summary: C++ library for filezilla
License: GPL-2.0-or-later
Group: Development/Libraries/C and C++
Url: https://lib.filezilla-project.org/
Source0: https://download.filezilla-project.org/libfilezilla/%{name}-%{version}.tar.…
-Source1: COPYING
Patch0: %{name}-date-time.patch
BuildRequires: autoconf
BuildRequires: automake
@@ -37,6 +36,7 @@
BuildRequires: libtool
BuildRequires: pkg-config
BuildRequires: pkgconfig(cppunit)
+BuildRequires: pkgconfig(nettle) >= 3.1
%if 0%{?suse_version} <= 1500
# FileZilla requires C++14 support.
BuildRequires: gcc7-c++
@@ -77,8 +77,6 @@
%prep
%setup -q
%patch0
-#copy in up to date GPL-2.0 license.
-cp -v %{SOURCE1} .
%build
%if 0%{?suse_version} <= 1500
@@ -111,7 +109,8 @@
%files -n %{libname}
%defattr(-,root,root)
-%doc AUTHORS ChangeLog NEWS README COPYING
+%license COPYING
+%doc AUTHORS ChangeLog NEWS README
%{_libdir}/%{name}.so.%{major}*
%files -n %{develname}
++++++ libfilezilla-0.14.0.tar.bz2 -> libfilezilla-0.15.0.tar.bz2 ++++++
++++ 2167 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/libfilezilla-0.14.0/INSTALL new/libfilezilla-0.15.0/INSTALL
--- old/libfilezilla-0.14.0/INSTALL 2017-07-10 19:43:37.000000000 +0200
+++ new/libfilezilla-0.15.0/INSTALL 2018-10-19 12:13:12.000000000 +0200
@@ -8,6 +8,7 @@
To compile libfilezilla, the following tools need to be installed:
- A C++14 compiler, e.g. a recent GCC or Clang
- GNU make
+- Nettle >= 3.1
Optional tools:
- recent automake, autoconf, libtool if you plan to change configure.in or
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/libfilezilla-0.14.0/NEWS new/libfilezilla-0.15.0/NEWS
--- old/libfilezilla-0.14.0/NEWS 2018-10-04 13:17:12.000000000 +0200
+++ new/libfilezilla-0.15.0/NEWS 2018-10-19 12:12:06.000000000 +0200
@@ -1,3 +1,13 @@
+0.15.0 (2018-10-19)
+
++ libfilezilla now depends on Nettle >= 3.1
++ Added fz::sha512, fz::sha256, fz::sha1 and fz::md5 hash functions
++ Added fz::hash_accumulator
++ Added fz::hmac_sha256 HMAC function
++ Added asymmetric encryption scheme using X25519
++ Added signature scheme using Ed25519
+- Changed and documented semantics of the return value of fz::remove_file, removing a non-existing file is not an error
+
0.14.0 (2018-10-04)
+ Added fz::equal_insensitive_ascii
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/libfilezilla-0.14.0/configure.ac new/libfilezilla-0.15.0/configure.ac
--- old/libfilezilla-0.14.0/configure.ac 2018-10-04 13:17:12.000000000 +0200
+++ new/libfilezilla-0.15.0/configure.ac 2018-10-19 12:00:57.000000000 +0200
@@ -1,4 +1,4 @@
-AC_INIT([libfilezilla],[0.14.0],[tim.kosse@filezilla-project.org],[],[https://lib.filezilla-project.org/])
+AC_INIT([libfilezilla],[0.15.0],[tim.kosse@filezilla-project.org],[],[https://lib.filezilla-project.org/])
AC_CONFIG_HEADERS([lib/libfilezilla/private/config.hpp])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR(config)
@@ -100,6 +100,23 @@
fi
+# Nettle
+# ------
+
+PKG_CHECK_MODULES([NETTLE], [nettle >= 3.1],, [
+ AC_MSG_ERROR([nettle 3.1 greater was not found. You can get it from https://www.lysator.liu.se/~nisse/nettle/]
+])
+
+AC_SUBST(NETTLE_LIBS)
+AC_SUBST(NETTLE_CFLAGS)
+
+PKG_CHECK_MODULES([HOGWEED], [hogweed >= 3.1],, [
+ AC_MSG_ERROR([hogweed 3.1 greater was not found. You can get it from https://www.lysator.liu.se/~nisse/nettle/]
+])
+
+AC_SUBST(HOGWEED_LIBS)
+AC_SUBST(HOGWEED_CFLAGS)
+
# Check for windres on MinGW builds
# ---------------------------------
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/libfilezilla-0.14.0/lib/Makefile.am new/libfilezilla-0.15.0/lib/Makefile.am
--- old/libfilezilla-0.14.0/lib/Makefile.am 2017-09-29 10:41:58.000000000 +0200
+++ new/libfilezilla-0.15.0/lib/Makefile.am 2018-10-19 12:00:50.000000000 +0200
@@ -3,15 +3,18 @@
libfilezilla_la_SOURCES = \
buffer.cpp \
encode.cpp \
+ encryption.cpp \
event.cpp \
event_handler.cpp \
event_loop.cpp \
file.cpp \
+ hash.cpp \
iputils.cpp \
local_filesys.cpp \
mutex.cpp \
process.cpp \
recursive_remove.cpp \
+ signature.cpp \
string.cpp \
thread.cpp \
thread_pool.cpp \
@@ -24,11 +27,13 @@
libfilezilla/apply.hpp \
libfilezilla/buffer.hpp \
libfilezilla/encode.hpp \
+ libfilezilla/encryption.hpp \
libfilezilla/event.hpp \
libfilezilla/event_handler.hpp \
libfilezilla/event_loop.hpp \
libfilezilla/file.hpp \
libfilezilla/format.hpp \
+ libfilezilla/hash.hpp \
libfilezilla/iputils.hpp \
libfilezilla/libfilezilla.hpp \
libfilezilla/local_filesys.hpp \
@@ -37,6 +42,7 @@
libfilezilla/process.hpp \
libfilezilla/recursive_remove.hpp \
libfilezilla/shared.hpp \
+ libfilezilla/signature.hpp \
libfilezilla/string.hpp \
libfilezilla/thread.hpp \
libfilezilla/thread_pool.hpp \
@@ -51,6 +57,7 @@
libfilezilla_la_CPPFLAGS = $(AM_CPPFLAGS)
libfilezilla_la_CPPFLAGS += -DBUILDING_LIBFILEZILLA
+libfilezilla_la_CPPFLAGS += $(NETTLE_CFLAGS)
# Needed for version.hpp in out-of-tree builds
libfilezilla_la_CPPFLAGS += -I$(srcdir)/libfilezilla
@@ -62,6 +69,8 @@
libfilezilla_la_LDFLAGS += -no-undefined
libfilezilla_la_LIBADD = $(libdeps)
+libfilezilla_la_LIBADD += $(NETTLE_LIBS) $(HOGWEED_LIBS)
+
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libfilezilla.pc
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/libfilezilla-0.14.0/lib/encode.cpp new/libfilezilla-0.15.0/lib/encode.cpp
--- old/libfilezilla-0.14.0/lib/encode.cpp 2018-05-06 11:22:43.000000000 +0200
+++ new/libfilezilla-0.15.0/lib/encode.cpp 2018-10-19 12:00:50.000000000 +0200
@@ -1,8 +1,13 @@
#include "libfilezilla/encode.hpp"
namespace fz {
-std::string base64_encode(std::string const& in, base64_type type, bool pad)
+
+namespace {
+template<typename DataContainer>
+std::string base64_encode_impl(DataContainer const& in, base64_type type, bool pad)
{
+ static_assert(sizeof(typename DataContainer::value_type) == 1, "Bad container type");
+
std::string::value_type const* const base64_chars =
(type == base64_type::standard)
? "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
@@ -47,6 +52,17 @@
return ret;
}
+}
+
+std::string base64_encode(std::string const& in, base64_type type, bool pad)
+{
+ return base64_encode_impl(in, type, pad);
+}
+
+std::string base64_encode(std::vector<uint8_t> const& in, base64_type type, bool pad)
+{
+ return base64_encode_impl(in, type, pad);
+}
std::string base64_decode(std::string const& in)
{
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/libfilezilla-0.14.0/lib/encryption.cpp new/libfilezilla-0.15.0/lib/encryption.cpp
--- old/libfilezilla-0.14.0/lib/encryption.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/encryption.cpp 2018-10-19 12:00:50.000000000 +0200
@@ -0,0 +1,271 @@
+#include "libfilezilla/encryption.hpp"
+
+#include "libfilezilla/encode.hpp"
+#include "libfilezilla/hash.hpp"
+#include "libfilezilla/util.hpp"
+
+#include <cstring>
+
+#include <nettle/aes.h>
+#include <nettle/ctr.h>
+#include <nettle/curve25519.h>
+#include <nettle/gcm.h>
+#include <nettle/memops.h>
+#include <nettle/pbkdf2.h>
+#include <nettle/sha2.h>
+
+namespace fz {
+
+std::string public_key::to_base64() const
+{
+ auto raw = std::string(key_.cbegin(), key_.cend());
+ raw += std::string(salt_.cbegin(), salt_.cend());
+ return fz::base64_encode(raw);
+}
+
+public_key public_key::from_base64(std::string const& base64)
+{
+ public_key ret;
+
+ auto raw = fz::base64_decode(base64);
+ if (raw.size() == key_size + salt_size) {
+ auto p = reinterpret_cast<uint8_t const*>(&raw[0]);
+ ret.key_.assign(p, p + key_size);
+ ret.salt_.assign(p + key_size, p + key_size + salt_size);
+ }
+
+ return ret;
+}
+
+private_key private_key::generate()
+{
+ private_key ret;
+
+ ret.key_ = fz::random_bytes(key_size);
+ ret.key_[0] &= 248;
+ ret.key_[31] &= 127;
+ ret.key_[31] |= 64;
+
+ ret.salt_ = fz::random_bytes(salt_size);
+
+ return ret;
+}
+
+public_key private_key::pubkey() const
+{
+ public_key ret;
+
+ if (*this) {
+ static const uint8_t nine[32]{
+ 9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ ret.key_.resize(32);
+ nettle_curve25519_mul(&ret.key_[0], &key_[0], nine);
+
+ ret.salt_ = salt_;
+ }
+
+ return ret;
+}
+
+private_key private_key::from_password(std::vector<uint8_t> const& password, std::vector<uint8_t> const& salt)
+{
+ private_key ret;
+
+ if (!password.empty() && salt.size() == salt_size) {
+
+ std::vector<uint8_t> key;
+ key.resize(key_size);
+ nettle_pbkdf2_hmac_sha256(password.size(), &password[0], 100000, salt_size, &salt[0], 32, &key[0]);
+ key[0] &= 248;
+ key[31] &= 127;
+ key[31] |= 64;
+
+ ret.key_ = std::move(key);
+ ret.salt_ = salt;
+ }
+
+ return ret;
+}
+
+std::string private_key::to_base64() const
+{
+ auto raw = std::string(key_.cbegin(), key_.cend());
+ raw += std::string(salt_.cbegin(), salt_.cend());
+ return fz::base64_encode(raw);
+}
+
+private_key private_key::from_base64(std::string const& base64)
+{
+ private_key ret;
+
+ auto raw = fz::base64_decode(base64);
+ if (raw.size() == key_size + salt_size) {
+ auto p = reinterpret_cast<uint8_t const*>(&raw[0]);
+ ret.key_.assign(p, p + key_size);
+ ret.key_[0] &= 248;
+ ret.key_[31] &= 127;
+ ret.key_[31] |= 64;
+ ret.salt_.assign(p + key_size, p + key_size + salt_size);
+ }
+
+ return ret;
+}
+
+
+std::vector<uint8_t> private_key::shared_secret(public_key const& pub) const
+{
+ std::vector<uint8_t> ret;
+
+ if (*this && pub) {
+ ret.resize(32);
+
+ nettle_curve25519_mul(&ret[0], &key_[0], &pub.key_[0]);
+ }
+
+ return ret;
+}
+
+std::vector<uint8_t> encrypt(uint8_t const* plain, size_t size, public_key const& pub, bool authenticated)
+{
+ std::vector<uint8_t> ret;
+
+ private_key ephemeral = private_key::generate();
+ public_key ephemeral_pub = ephemeral.pubkey();
+
+ if (pub && ephemeral && ephemeral_pub) {
+ // Generate shared secret from pub and ephemeral
+ std::vector<uint8_t> secret = ephemeral.shared_secret(pub);
+
+ // Derive AES2556 key and CTR nonce from shared secret
+ std::vector<uint8_t> const aes_key = hash_accumulator(hash_algorithm::sha256) << ephemeral_pub.salt_ << 0 << secret << ephemeral_pub.key_ << pub.key_ << pub.salt_;
+
+ if (authenticated) {
+ std::vector<uint8_t> iv = hash_accumulator(hash_algorithm::sha256) << ephemeral_pub.salt_ << 2 << secret << ephemeral_pub.key_ << pub.key_ << pub.salt_;
+ static_assert(SHA256_DIGEST_SIZE >= GCM_IV_SIZE, "iv too small");
+ iv.resize(GCM_IV_SIZE);
+
+ gcm_aes256_ctx ctx;
+ nettle_gcm_aes256_set_key(&ctx, &aes_key[0]);
+ nettle_gcm_aes256_set_iv(&ctx, GCM_IV_SIZE, &iv[0]);
+
+ // Encrypt plaintext with AES256-GCM
+ ret.resize(public_key::key_size + public_key::salt_size + size + GCM_DIGEST_SIZE);
+ if (size) {
+ nettle_gcm_aes256_encrypt(&ctx, size, &ret[public_key::key_size + public_key::salt_size], plain);
+ }
+
+ // Return ephemeral_pub.key_||ephemeral_pub.salt_||ciphertext||tag
+ memcpy(&ret[0], &ephemeral_pub.key_[0], public_key::key_size);
+ memcpy(&ret[public_key::key_size], &ephemeral_pub.salt_[0], public_key::salt_size);
+ nettle_gcm_aes256_digest(&ctx, GCM_DIGEST_SIZE, &ret[public_key::key_size + public_key::salt_size + size]);
+ }
+ else {
+ std::vector<uint8_t> ctr = hash_accumulator(hash_algorithm::sha256) << ephemeral_pub.salt_ << 1 << secret << ephemeral_pub.key_ << pub.key_ << pub.salt_;
+
+ aes256_ctx ctx;
+ nettle_aes256_set_encrypt_key(&ctx, &aes_key[0]);
+
+ // Encrypt plaintext with AES256-CTR
+ ret.resize(public_key::key_size + public_key::salt_size + size);
+ if (size) {
+ nettle_ctr_crypt(&ctx, reinterpret_cast<nettle_cipher_func*>(nettle_aes256_encrypt), 16, &ctr[0], size, &ret[public_key::key_size + public_key::salt_size], plain);
+ }
+
+ // Return ephemeral_pub.key_||ephemeral_pub.salt_||ciphertext
+ memcpy(&ret[0], &ephemeral_pub.key_[0], public_key::key_size);
+ memcpy(&ret[public_key::key_size], &ephemeral_pub.salt_[0], public_key::salt_size);
+ }
+ }
+
+ return ret;
+}
+
+std::vector<uint8_t> encrypt(std::vector<uint8_t> const& plain, public_key const& pub, bool authenticated)
+{
+ return encrypt(plain.data(), plain.size(), pub, authenticated);
+}
+
+std::vector<uint8_t> encrypt(std::string const& plain, public_key const& pub, bool authenticated)
+{
+ return encrypt(reinterpret_cast<uint8_t const*>(plain.c_str()), plain.size(), pub, authenticated);
+}
+
+std::vector<uint8_t> decrypt(uint8_t const* cipher, size_t size, private_key const& priv, bool authenticated)
+{
+ size_t const overhead = public_key::key_size + public_key::salt_size + (authenticated ? GCM_DIGEST_SIZE : 0);
+
+ std::vector<uint8_t> ret;
+
+ if (priv && size >= overhead && cipher) {
+ size_t const message_size = size - overhead;
+
+ // Extract ephemeral_pub from cipher
+ public_key ephemeral_pub;
+ ephemeral_pub.key_.resize(public_key::key_size);
+ ephemeral_pub.salt_.resize(public_key::salt_size);
+ memcpy(&ephemeral_pub.key_[0], cipher, public_key::key_size);
+ memcpy(&ephemeral_pub.salt_[0], cipher + public_key::key_size, public_key::salt_size);
+
+ // Generate shared secret from ephemeral_pub and priv
+ std::vector<uint8_t> const secret = priv.shared_secret(ephemeral_pub);
+
+ public_key const pub = priv.pubkey();
+ std::vector<uint8_t> const aes_key = hash_accumulator(hash_algorithm::sha256) << ephemeral_pub.salt_ << 0 << secret << ephemeral_pub.key_ << pub.key_ << pub.salt_;
+
+ if (authenticated) {
+ // Derive AES2556 key and GCM IV from shared secret
+ std::vector<uint8_t> iv = hash_accumulator(hash_algorithm::sha256) << ephemeral_pub.salt_ << 2 << secret << ephemeral_pub.key_ << pub.key_ << pub.salt_;
+ static_assert(SHA256_DIGEST_SIZE >= GCM_IV_SIZE, "iv too small");
+ iv.resize(GCM_IV_SIZE);
+
+ gcm_aes256_ctx ctx;
+ nettle_gcm_aes256_set_key(&ctx, &aes_key[0]);
+ nettle_gcm_aes256_set_iv(&ctx, GCM_IV_SIZE, &iv[0]);
+
+ // Decrypt ciphertext with AES256-GCM
+ ret.resize(message_size);
+ if (message_size) {
+ nettle_gcm_aes256_decrypt(&ctx, message_size, &ret[0], cipher +public_key::key_size + public_key::salt_size);
+ }
+
+ // Last but not least, verify the tag
+ uint8_t tag[GCM_DIGEST_SIZE];
+ nettle_gcm_aes256_digest(&ctx, GCM_DIGEST_SIZE, tag);
+ if (!nettle_memeql_sec(tag, cipher + size - GCM_DIGEST_SIZE, GCM_DIGEST_SIZE)) {
+ ret.clear();
+ }
+ }
+ else {
+ // Derive AES2556 key and CTR nonce from shared secret
+ std::vector<uint8_t> ctr = hash_accumulator(hash_algorithm::sha256) << ephemeral_pub.salt_ << 1 << secret << ephemeral_pub.key_ << pub.key_ << pub.salt_;
+
+ aes256_ctx ctx;
+ nettle_aes256_set_encrypt_key(&ctx, &aes_key[0]);
+
+ // Decrypt ciphertext with AES256-CTR
+ ret.resize(message_size);
+ if (message_size) {
+ nettle_ctr_crypt(&ctx, reinterpret_cast<nettle_cipher_func*>(nettle_aes256_encrypt), 16, &ctr[0], ret.size(), &ret[0], &cipher[public_key::key_size + public_key::salt_size]);
+ }
+ }
+ }
+
+ // Return the plaintext
+ return ret;
+}
+
+std::vector<uint8_t> decrypt(std::vector<uint8_t> const& cipher, private_key const& priv, bool authenticated)
+{
+ return decrypt(cipher.data(), cipher.size(), priv, authenticated);
+}
+
+std::vector<uint8_t> decrypt(std::string const& cipher, private_key const& priv, bool authenticated)
+{
+ return decrypt(reinterpret_cast<uint8_t const*>(cipher.c_str()), cipher.size(), priv, authenticated);
+}
+
+}
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/libfilezilla-0.14.0/lib/file.cpp new/libfilezilla-0.15.0/lib/file.cpp
--- old/libfilezilla-0.14.0/lib/file.cpp 2017-10-30 18:14:16.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/file.cpp 2018-10-19 12:00:50.000000000 +0200
@@ -126,7 +126,12 @@
bool remove_file(fz::native_string const& name)
{
- return DeleteFileW(name.c_str()) != 0;
+ bool ret = DeleteFileW(name.c_str()) != 0;
+ if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) {
+ ret = true;
+ }
+
+ return ret;
}
bool file::fsync()
@@ -242,7 +247,11 @@
bool remove_file(fz::native_string const& name)
{
- return unlink(name.c_str()) == 0;
+ bool ret = unlink(name.c_str()) == 0;
+ if (!ret && errno == ENOENT) {
+ ret = true;
+ }
+ return ret;
}
bool file::fsync()
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/libfilezilla-0.14.0/lib/hash.cpp new/libfilezilla-0.15.0/lib/hash.cpp
--- old/libfilezilla-0.14.0/lib/hash.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/hash.cpp 2018-10-19 12:00:50.000000000 +0200
@@ -0,0 +1,311 @@
+#include "libfilezilla/libfilezilla.hpp"
+
+#include "libfilezilla/hash.hpp"
+
+#include <nettle/md5.h>
+#include <nettle/sha2.h>
+#include <nettle/hmac.h>
+
+namespace fz {
+
+class hash_accumulator::impl
+{
+public:
+ virtual ~impl() = default;
+
+ virtual void update(uint8_t const* data, size_t size) = 0;
+ virtual void reinit() = 0;
+ virtual std::vector<uint8_t> digest() = 0;
+};
+
+class hash_accumulator_md5 final : public hash_accumulator::impl
+{
+public:
+ virtual void update(uint8_t const* data, size_t size) override
+ {
+ nettle_md5_update(&ctx_, size, data);
+ }
+
+ virtual void reinit() override
+ {
+ nettle_md5_init(&ctx_);
+ }
+
+ virtual std::vector<uint8_t> digest() override
+ {
+ std::vector<uint8_t> ret;
+ ret.resize(MD5_DIGEST_SIZE);
+ nettle_md5_digest(&ctx_, ret.size(), &ret[0]);
+ return ret;
+ }
+
+private:
+ md5_ctx ctx_;
+};
+
+class hash_accumulator_sha1 final : public hash_accumulator::impl
+{
+public:
+ virtual void update(uint8_t const* data, size_t size) override
+ {
+ nettle_sha1_update(&ctx_, size, data);
+ }
+
+ virtual void reinit() override
+ {
+ nettle_sha1_init(&ctx_);
+ }
+
+ virtual std::vector<uint8_t> digest() override
+ {
+ std::vector<uint8_t> ret;
+ ret.resize(SHA1_DIGEST_SIZE);
+ nettle_sha1_digest(&ctx_, ret.size(), &ret[0]);
+ return ret;
+ }
+
+private:
+ sha1_ctx ctx_;
+};
+
+class hash_accumulator_sha256 final : public hash_accumulator::impl
+{
+public:
+ virtual void update(uint8_t const* data, size_t size) override
+ {
+ nettle_sha256_update(&ctx_, size, data);
+ }
+
+ virtual void reinit() override
+ {
+ nettle_sha256_init(&ctx_);
+ }
+
+ virtual std::vector<uint8_t> digest() override
+ {
+ std::vector<uint8_t> ret;
+ ret.resize(SHA256_DIGEST_SIZE);
+ nettle_sha256_digest(&ctx_, ret.size(), &ret[0]);
+ return ret;
+ }
+
+private:
+ sha256_ctx ctx_;
+};
+
+class hash_accumulator_sha512 final : public hash_accumulator::impl
+{
+public:
+ virtual void update(uint8_t const* data, size_t size) override
+ {
+ nettle_sha512_update(&ctx_, size, data);
+ }
+
+ virtual void reinit() override
+ {
+ nettle_sha512_init(&ctx_);
+ }
+
+ virtual std::vector<uint8_t> digest() override
+ {
+ std::vector<uint8_t> ret;
+ ret.resize(SHA512_DIGEST_SIZE);
+ nettle_sha512_digest(&ctx_, ret.size(), &ret[0]);
+ return ret;
+ }
+
+private:
+ sha512_ctx ctx_;
+};
+
+hash_accumulator::hash_accumulator(hash_algorithm algorithm)
+{
+ switch (algorithm) {
+ case hash_algorithm::md5:
+ impl_ = new hash_accumulator_md5;
+ break;
+ case hash_algorithm::sha1:
+ impl_ = new hash_accumulator_sha1;
+ break;
+ case hash_algorithm::sha256:
+ impl_ = new hash_accumulator_sha256;
+ break;
+ case hash_algorithm::sha512:
+ impl_ = new hash_accumulator_sha512;
+ break;
+ }
+
+ impl_->reinit();
+}
+
+hash_accumulator::~hash_accumulator()
+{
+ delete impl_;
+}
+
+void hash_accumulator::reinit()
+{
+ impl_->reinit();
+}
+
+void hash_accumulator::update(std::string const& data)
+{
+ if (!data.empty()) {
+ impl_->update(reinterpret_cast<uint8_t const*>(&data[0]), data.size());
+ }
+}
+
+void hash_accumulator::update(std::vector<uint8_t> const& data)
+{
+ if (!data.empty()) {
+ impl_->update(&data[0], data.size());
+ }
+}
+
+void hash_accumulator::update(uint8_t const* data, size_t size)
+{
+ impl_->update(data, size);
+}
+
+std::vector<uint8_t> hash_accumulator::digest()
+{
+ return impl_->digest();
+}
+
+namespace {
+// In C++17, require ContiguousContainer
+template<typename DataContainer>
+std::vector<uint8_t> md5_impl(DataContainer const& in)
+{
+ static_assert(sizeof(typename DataContainer::value_type) == 1, "Bad container type");
+
+ hash_accumulator_md5 acc;
+ acc.reinit();
+ if (!in.empty()) {
+ acc.update(reinterpret_cast<uint8_t const*>(&in[0]), in.size());
+ }
+ return acc.digest();
+}
+
+template<typename DataContainer>
+std::vector<uint8_t> sha1_impl(DataContainer const& in)
+{
+ static_assert(sizeof(typename DataContainer::value_type) == 1, "Bad container type");
+
+ hash_accumulator_sha1 acc;
+ acc.reinit();
+ if (!in.empty()) {
+ acc.update(reinterpret_cast<uint8_t const*>(&in[0]), in.size());
+ }
+ return acc.digest();
+}
+
+template<typename DataContainer>
+std::vector<uint8_t> sha256_impl(DataContainer const& in)
+{
+ static_assert(sizeof(typename DataContainer::value_type) == 1, "Bad container type");
+
+ hash_accumulator_sha256 acc;
+ acc.reinit();
+ if (!in.empty()) {
+ acc.update(reinterpret_cast<uint8_t const*>(&in[0]), in.size());
+ }
+ return acc.digest();
+}
+
+template<typename DataContainer>
+std::vector<uint8_t> sha512_impl(DataContainer const& in)
+{
+ static_assert(sizeof(typename DataContainer::value_type) == 1, "Bad container type");
+
+ hash_accumulator_sha512 acc;
+ acc.reinit();
+ if (!in.empty()) {
+ acc.update(reinterpret_cast<uint8_t const*>(&in[0]), in.size());
+ }
+ return acc.digest();
+}
+
+template<typename KeyContainer, typename DataContainer>
+std::vector<uint8_t> hmac_sha256_impl(KeyContainer const& key, DataContainer const& data)
+{
+ static_assert(sizeof(typename KeyContainer::value_type) == 1, "Bad container type");
+ static_assert(sizeof(typename DataContainer::value_type) == 1, "Bad container type");
+
+ std::vector<uint8_t> ret;
+
+ hmac_sha256_ctx ctx;
+ nettle_hmac_sha256_set_key(&ctx, key.size(), key.empty() ? nullptr : reinterpret_cast<uint8_t const*>(&key[0]));
+
+ if (!data.empty()) {
+ nettle_hmac_sha256_update(&ctx, data.size(), reinterpret_cast<uint8_t const*>(&data[0]));
+ }
+
+ ret.resize(SHA256_DIGEST_SIZE);
+ nettle_hmac_sha256_digest(&ctx, ret.size(), &ret[0]);
+
+ return ret;
+}
+}
+
+std::vector<uint8_t> md5(std::vector<uint8_t> const& data)
+{
+ return md5_impl(data);
+}
+
+std::vector<uint8_t> md5(std::string const& data)
+{
+ return md5_impl(data);
+}
+
+std::vector<uint8_t> sha1(std::vector<uint8_t> const& data)
+{
+ return sha1_impl(data);
+}
+
+std::vector<uint8_t> sha1(std::string const& data)
+{
+ return sha1_impl(data);
+}
+
+std::vector<uint8_t> sha256(std::vector<uint8_t> const& data)
+{
+ return sha256_impl(data);
+}
+
+std::vector<uint8_t> sha256(std::string const& data)
+{
+ return sha256_impl(data);
+}
+
+std::vector<uint8_t> sha512(std::vector<uint8_t> const& data)
+{
+ return sha512_impl(data);
+}
+
+std::vector<uint8_t> sha512(std::string const& data)
+{
+ return sha512_impl(data);
+}
+
+std::vector<uint8_t> hmac_sha256(std::string const& key, std::string const& data)
+{
+ return hmac_sha256_impl(key, data);
+}
+
+std::vector<uint8_t> hmac_sha256(std::vector<uint8_t> const& key, std::vector<uint8_t> const& data)
+{
+ return hmac_sha256_impl(key, data);
+}
+
+std::vector<uint8_t> hmac_sha256(std::vector<uint8_t> const& key, std::string const& data)
+{
+ return hmac_sha256_impl(key, data);
+}
+
+std::vector<uint8_t> hmac_sha256(std::string const& key, std::vector<uint8_t> const& data)
+{
+ return hmac_sha256_impl(key, data);
+}
+
+}
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/libfilezilla-0.14.0/lib/libfilezilla/encode.hpp new/libfilezilla-0.15.0/lib/libfilezilla/encode.hpp
--- old/libfilezilla-0.14.0/lib/libfilezilla/encode.hpp 2018-05-06 11:22:43.000000000 +0200
+++ new/libfilezilla-0.15.0/lib/libfilezilla/encode.hpp 2018-10-19 12:00:50.000000000 +0200
@@ -98,6 +98,7 @@
/// \brief Encodes raw input string to base64
std::string FZ_PUBLIC_SYMBOL base64_encode(std::string const& in, base64_type type = base64_type::standard, bool pad = true);
+std::string FZ_PUBLIC_SYMBOL base64_encode(std::vector<uint8_t> const& in, base64_type type = base64_type::standard, bool pad = true);
/**
* \brief Decodes base64, ignores whitespace. Returns empty string on invalid input.
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/libfilezilla-0.14.0/lib/libfilezilla/encryption.hpp new/libfilezilla-0.15.0/lib/libfilezilla/encryption.hpp
--- old/libfilezilla-0.14.0/lib/libfilezilla/encryption.hpp 1970-01-01 01:00:00.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/libfilezilla/encryption.hpp 2018-10-19 12:14:34.000000000 +0200
@@ -0,0 +1,153 @@
+#ifndef LIBFILEZILLA_ENCRYPTION_HEADER
+#define LIBFILEZILLA_ENCRYPTION_HEADER
+
+/** \file
+ * \brief Asymmetric encryption scheme using X25519
+ *
+ * See RFC 7748 for the X22519 specs.
+ */
+
+#include "libfilezilla.hpp"
+
+#include <vector>
+#include <string>
+
+namespace fz {
+
+/** \brief Represents a X25519 public key with associated salt
+ *
+ * \sa private_key
+ */
+class FZ_PUBLIC_SYMBOL public_key
+{
+public:
+ /// Size in octets of key and salt.
+ enum {
+ key_size = 32,
+ salt_size = 32
+ };
+
+ explicit operator bool() const {
+ return key_.size() == key_size && salt_.size() == salt_size;
+ }
+
+ bool operator==(public_key const& rhs) const {
+ return key_ == rhs.key_ && salt_ == rhs.salt_;
+ }
+
+ bool operator!=(public_key const& rhs) const {
+ return !(*this == rhs);
+ }
+
+ bool operator<(public_key const& rhs) const {
+ return key_ < rhs.key_ || (key_ == rhs.key_ && salt_ < rhs.salt_);
+ }
+
+ std::string to_base64() const;
+ static public_key from_base64(std::string const& base64);
+
+ std::vector<uint8_t> key_;
+ std::vector<uint8_t> salt_;
+};
+
+/** \brief Represents a X25519 private key with associated salt
+ *
+ * \sa public_key
+ */
+class FZ_PUBLIC_SYMBOL private_key
+{
+public:
+ /// Size in octets of key an salt.
+ enum {
+ key_size = 32,
+ salt_size = 32
+ };
+
+ /// Generates a random private key
+ static private_key generate();
+
+ /// Derives a private key using PKBDF2-SHA256 from the given password and salt
+ static private_key from_password(std::vector<uint8_t> const& password, std::vector<uint8_t> const& salt);
+ static private_key from_password(std::string const& password, std::vector<uint8_t> const& salt)
+ {
+ return from_password(std::vector<uint8_t>(password.begin(), password.end()), salt);
+ }
+
+ explicit operator bool() const {
+ return key_.size() == key_size && salt_.size() == salt_size;
+ }
+
+ std::vector<uint8_t> const& salt() const {
+ return salt_;
+ }
+
+ /// Calculates the public key corresponding to the private key
+ public_key pubkey() const;
+
+ /// Calculates a shared secret using Elliptic Curve Diffie-Hellman on Curve25519 (X25519)
+ std::vector<uint8_t> shared_secret(public_key const& pub) const;
+
+ std::string to_base64() const;
+ static private_key from_base64(std::string const& base64);
+
+private:
+ std::vector<uint8_t> key_;
+ std::vector<uint8_t> salt_;
+};
+
+/** \brief Encrypt the plaintext to the given public key.
+ *
+ * \param authenticated if true, authenticated encryption is used.
+ *
+ * \par Encryption algorithm:
+ *
+ * Let \e M_pub be the key portion, S_e be the salt portion of the pub parameter and \e P be the plaintext.
+ *
+ * - First an ephemeral private key \e E_priv with corresponding public key \e E_pub and \e S_e is randomly generated
+ * - Using ECDH on Curve25519 (X25519), a shared secret \e R is derived:\n
+ * <tt>R := X25519(E_priv, M_pub)</tt>
+ * - From \e R, a symmetric AES256 key \e K and a nonce \e IV are derived:
+ * * <tt>K := SHA256(S_e || 0 || S || E_pub || M_pub || S_m)</tt>
+ * * <tt>IV := SHA256(S_e || 2 || S || E_pub || M_pub || S_m)</tt> if authenticated,\n
+ * <tt>IV := SHA256(S_e || 1 || S || E_pub || M_pub || S_m)</tt> otherwise
+ * - The plaintext is encrypted into the ciphertext \e C' and authentication tag \e T using\n
+ * <tt>C', T := AES256-GCM(K, IV, P)</tt> if authenticated,\n
+ * <tt>C' := AES256-CTR(K, IV, P)</tt> T:='' otherwise
+ * - The ciphertext \e C is returned, containing \e E_pub, \e S_e and \e T: \n
+ * <tt>C := E_pub || S_e || C' || T</tt>
+ */
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL encrypt(std::vector<uint8_t> const& plain, public_key const& pub, bool authenticated = true);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL encrypt(std::string const& plain, public_key const& pub, bool authenticated = true);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL encrypt(uint8_t const* plain, size_t size, public_key const& pub, bool authenticated = true);
+
+/** \brief Decrypt the ciphertext using the given private key.
+ *
+ * \param priv The private matching the public key that was originally used to encrypt the data
+ * \param authenticated if true, authenticated encryption is used.
+ *
+ * \returns plaintext on success, empty container on failure
+ *
+ * \par Decryption algorithm:
+ *
+ * Let \e M_priv be the key portion and \e S_m be the salt portion of the priv parameter and \e C the ciphertext.
+ *
+ * - First \e C is split into \e E_pub, \e S_e, \e C' and \e T such that\n
+ * <tt>C: = E_pub || S_e || C1 || T</tt>
+ * - \e M_pub is calculated from \e M_priv
+ * - Using ECDH on Curve25519 (X25519), the shared secret \e R is recovered:\n
+ * <tt>R := X25519(M_priv, E_pub)</tt>
+ * - From \e R, a symmetric AES256 key \e K and a nonce \e IV are derived:
+ * * <tt>K := SHA256(S_e || 0 || S || E_pub || M_pub || S_m)</tt>
+ * * <tt>IV := SHA256(S_e || 2 || S || E_pub || M_pub || S_m)</tt> if authenticated,\n
+ * <tt>IV := SHA256(S_e || 1 || S || E_pub || M_pub || S_m)</tt> otherwise
+ * - The ciphertext is decrypted into the plaintext \e P using\n
+ * <tt>P, T' := AES256-GCM(K, IV, C')</tt> if authenticated,\n
+ * <tt>P := AES256-CTR(K, IV, C'), T:=''</tt> otherwise
+ * - If the calculated \e T' matches \e T, then \e P is returned, otherwise decryption has failed and nothing is returned.
+ */
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL decrypt(std::vector<uint8_t> const& chiper, private_key const& priv, bool authenticated = true);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL decrypt(std::string const& chiper, private_key const& priv, bool authenticated = true);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL decrypt(uint8_t const* cipher, size_t size, private_key const& priv, bool authenticated = true);
+
+}
+#endif
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/libfilezilla-0.14.0/lib/libfilezilla/file.hpp new/libfilezilla-0.15.0/lib/libfilezilla/file.hpp
--- old/libfilezilla-0.14.0/lib/libfilezilla/file.hpp 2017-10-30 18:14:16.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/libfilezilla/file.hpp 2018-10-19 12:00:50.000000000 +0200
@@ -142,6 +142,10 @@
#endif
};
+/** \brief remove the specified file.
+ *
+ * \return true iff the file has been removed or did not exist to begin with.
+ */
bool FZ_PUBLIC_SYMBOL remove_file(native_string const& name);
}
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/libfilezilla-0.14.0/lib/libfilezilla/hash.hpp new/libfilezilla-0.15.0/lib/libfilezilla/hash.hpp
--- old/libfilezilla-0.14.0/lib/libfilezilla/hash.hpp 1970-01-01 01:00:00.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/libfilezilla/hash.hpp 2018-10-19 12:00:50.000000000 +0200
@@ -0,0 +1,81 @@
+#ifndef LIBFILEZILLA_HASH_HEADER
+#define LIBFILEZILLA_HASH_HEADER
+
+/** \file
+ * \brief Collection of cryptographic hash and MAC functions
+ */
+
+#include "libfilezilla.hpp"
+
+#include <vector>
+#include <string>
+
+namespace fz {
+
+/// List of supported hashing algorithms
+enum class hash_algorithm
+{
+ md5,
+ sha1,
+ sha256,
+ sha512
+};
+
+/// Accumulator for hashing large amounts of data
+class FZ_PUBLIC_SYMBOL hash_accumulator final
+{
+public:
+ /// Creates an initialized accumulator for the passed algorithm
+ hash_accumulator(hash_algorithm algorithm);
+ ~hash_accumulator();
+
+ hash_accumulator(hash_accumulator const&) = delete;
+ hash_accumulator& operator=(hash_accumulator const&) = delete;
+
+ void reinit();
+
+ void update(std::string const& data);
+ void update(std::vector<uint8_t> const& data);
+ void update(uint8_t const* data, size_t size);
+ void update(uint8_t in) {
+ update(&in, 1);
+ }
+
+ /// Returns the raw digest and reinitalizes the accumulator
+ std::vector<uint8_t> digest();
+
+ operator std::vector<uint8_t>() {
+ return digest();
+ }
+
+ template<typename T>
+ hash_accumulator& operator<<(T && in) {
+ update(std::forward<T>(in));
+ return *this;
+ }
+
+ class impl;
+private:
+ impl* impl_;
+};
+
+/** \brief Standard MD5
+ *
+ * Insecure, avoid using this
+ */
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL md5(std::string const& data);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL md5(std::vector<uint8_t> const& data);
+
+/// \brief Standard SHA256
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL sha256(std::string const& data);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL sha256(std::vector<uint8_t> const& data);
+
+/// \brief Standard HMAC using SHA256
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL hmac_sha256(std::string const& key, std::string const& data);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL hmac_sha256(std::vector<uint8_t> const& key, std::vector<uint8_t> const& data);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL hmac_sha256(std::vector<uint8_t> const& key, std::string const& data);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL hmac_sha256(std::string const& key, std::vector<uint8_t> const& data);
+
+}
+
+#endif
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/libfilezilla-0.14.0/lib/libfilezilla/signature.hpp new/libfilezilla-0.15.0/lib/libfilezilla/signature.hpp
--- old/libfilezilla-0.14.0/lib/libfilezilla/signature.hpp 1970-01-01 01:00:00.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/libfilezilla/signature.hpp 2018-10-19 12:00:50.000000000 +0200
@@ -0,0 +1,98 @@
+#ifndef LIBFILEZILLA_SIGNATURE_HEADER
+#define LIBFILEZILLA_SIGNATURE_HEADER
+
+/** \file
+ * \brief Signature scheme using Ed25519
+ *
+ * See RFC 8032 for the X22519 specs.
+ */
+
+#include "libfilezilla.hpp"
+
+#include <vector>
+#include <string>
+
+namespace fz {
+
+/** \brief Represents a public key to verify messages signed using Ed25519.
+ *
+ * \sa private_signing_key
+ */
+class FZ_PUBLIC_SYMBOL public_verification_key
+{
+public:
+ enum {
+ key_size = 32
+ };
+
+ explicit operator bool() const {
+ return key_.size() == key_size;
+ }
+
+ bool operator==(public_verification_key const& rhs) const {
+ return key_ == rhs.key_;
+ }
+
+ bool operator!=(public_verification_key const& rhs) const {
+ return !(*this == rhs);
+ }
+
+ bool operator<(public_verification_key const& rhs) const {
+ return key_ < rhs.key_;
+ }
+
+ std::string to_base64() const;
+ static public_verification_key from_base64(std::string const& base64);
+
+ std::vector<uint8_t> key_;
+};
+
+/** \brief Represents a private key to sign message with using Ed25519.
+ *
+ * \sa public_verification_key
+ */
+class FZ_PUBLIC_SYMBOL private_signing_key
+{
+public:
+ enum {
+ key_size = 32
+ };
+
+ /// Generates a random private key
+ static private_signing_key generate();
+
+ explicit operator bool() const {
+ return key_.size() == key_size;
+ }
+
+ /// Gets the public key corresponding to the private key
+ public_verification_key pubkey() const;
+
+ std::vector<uint8_t> const& data() const {
+ return key_;
+ }
+
+ std::string to_base64() const; // Keep secret!
+ static private_signing_key from_base64(std::string const& base64);
+
+private:
+ std::vector<uint8_t> key_;
+};
+
+enum {
+ signature_size = 64
+};
+
+/// Returns the message with the signature appended, created using the passed private key
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL sign(std::vector<uint8_t> const& message, private_signing_key const& priv);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL sign(std::string const& message, private_signing_key const& priv);
+std::vector<uint8_t> FZ_PUBLIC_SYMBOL sign(uint8_t const& message, size_t const size, private_signing_key const& priv);
+
+/// Verify the message. Returns true iff it has been signed by the private key corresponding to the passed public key
+bool FZ_PUBLIC_SYMBOL verify(std::vector<uint8_t> const& message, public_verification_key const& pub);
+bool FZ_PUBLIC_SYMBOL verify(std::string const& message, public_verification_key const& pub);
+bool FZ_PUBLIC_SYMBOL verify(uint8_t const* message, size_t const size, public_verification_key const& pub);
+
+}
+
+#endif
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/libfilezilla-0.14.0/lib/libfilezilla/version.hpp new/libfilezilla-0.15.0/lib/libfilezilla/version.hpp
--- old/libfilezilla-0.14.0/lib/libfilezilla/version.hpp 2018-10-04 13:17:21.000000000 +0200
+++ new/libfilezilla-0.15.0/lib/libfilezilla/version.hpp 2018-10-19 12:14:45.000000000 +0200
@@ -9,15 +9,15 @@
#include <tuple>
/// \brief Version string of the libfilezilla headers
-#define LIBFILEZILLA_VERSION "0.14.0"
+#define LIBFILEZILLA_VERSION "0.15.0"
#define LIBFILEZILLA_VERSION_MAJOR 0
-#define LIBFILEZILLA_VERSION_MINOR 14
+#define LIBFILEZILLA_VERSION_MINOR 15
#define LIBFILEZILLA_VERSION_MICRO 0
#define LIBFILEZILLA_VERSION_NANO 0
/// \brief Suffix string, e.g. "rc1"
-#define LIBFILEZILLA_VERSION_SUFFIX "0.14.0"
+#define LIBFILEZILLA_VERSION_SUFFIX "0.15.0"
namespace fz {
/// \brief Get version string of libfilezilla
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/libfilezilla-0.14.0/lib/libfilezilla.pc.in new/libfilezilla-0.15.0/lib/libfilezilla.pc.in
--- old/libfilezilla-0.14.0/lib/libfilezilla.pc.in 2015-11-02 14:47:31.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/libfilezilla.pc.in 2018-10-19 12:00:50.000000000 +0200
@@ -9,3 +9,4 @@
Version: @PACKAGE_VERSION@
CFlags: -I${includedir}
Libs: -L${libdir} -lfilezilla @libdeps@
+Requires.private: nettle >= 3.1, hogweed >= 3.1
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/libfilezilla-0.14.0/lib/libfilezilla.vcxproj new/libfilezilla-0.15.0/lib/libfilezilla.vcxproj
--- old/libfilezilla-0.14.0/lib/libfilezilla.vcxproj 2017-09-29 10:41:58.000000000 +0200
+++ new/libfilezilla-0.15.0/lib/libfilezilla.vcxproj 2018-10-19 12:00:50.000000000 +0200
@@ -66,6 +66,9 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="..\Dependencies.props" />
+ </ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>$(ProjectDir)$(Platform)_$(Configuration)\</OutDir>
@@ -81,7 +84,7 @@
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
- <WarningLevel>Level3</WarningLevel>
+ <WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
@@ -137,7 +140,6 @@
<OmitFramePointers>true</OmitFramePointers>
<PreprocessorDefinitions>BUILDING_LIBFILEZILLA;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
@@ -188,10 +190,12 @@
<ItemGroup>
<ClCompile Include="buffer.cpp" />
<ClCompile Include="encode.cpp" />
+ <ClCompile Include="encryption.cpp" />
<ClCompile Include="event.cpp" />
<ClCompile Include="event_handler.cpp" />
<ClCompile Include="event_loop.cpp" />
<ClCompile Include="file.cpp" />
+ <ClCompile Include="hash.cpp" />
<ClCompile Include="iputils.cpp" />
<ClCompile Include="local_filesys.cpp" />
<ClCompile Include="mutex.cpp" />
@@ -209,11 +213,13 @@
<ClInclude Include="libfilezilla\apply.hpp" />
<ClInclude Include="libfilezilla\buffer.hpp" />
<ClInclude Include="libfilezilla\encode.hpp" />
+ <ClInclude Include="libfilezilla\encryption.hpp" />
<ClInclude Include="libfilezilla\event.hpp" />
<ClInclude Include="libfilezilla\event_handler.hpp" />
<ClInclude Include="libfilezilla\event_loop.hpp" />
<ClInclude Include="libfilezilla\file.hpp" />
<ClInclude Include="libfilezilla\format.hpp" />
+ <ClInclude Include="libfilezilla\hash.hpp" />
<ClInclude Include="libfilezilla\iputils.hpp" />
<ClInclude Include="libfilezilla\libfilezilla.hpp" />
<ClInclude Include="libfilezilla\local_filesys.hpp" />
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/libfilezilla-0.14.0/lib/signature.cpp new/libfilezilla-0.15.0/lib/signature.cpp
--- old/libfilezilla-0.14.0/lib/signature.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new/libfilezilla-0.15.0/lib/signature.cpp 2018-10-19 12:00:50.000000000 +0200
@@ -0,0 +1,115 @@
+#include "libfilezilla/signature.hpp"
+
+#include "libfilezilla/encode.hpp"
+#include "libfilezilla/util.hpp"
+
+#include <nettle/eddsa.h>
+
+namespace fz {
+
+std::string public_verification_key::to_base64() const
+{
+ auto raw = std::string(key_.cbegin(), key_.cend());
+ return fz::base64_encode(raw);
+}
+
+public_verification_key public_verification_key::from_base64(std::string const& base64)
+{
+ public_verification_key ret;
+
+ auto raw = fz::base64_decode(base64);
+ if (raw.size() == key_size) {
+ auto p = reinterpret_cast<uint8_t const*>(&raw[0]);
+ ret.key_.assign(p, p + key_size);
+ }
+
+ return ret;
+}
+
+private_signing_key private_signing_key::generate()
+{
+ private_signing_key ret;
+
+ ret.key_ = fz::random_bytes(key_size);
+ return ret;
+}
+
+std::string private_signing_key::to_base64() const
+{
+ auto raw = std::string(key_.cbegin(), key_.cend());
+ return fz::base64_encode(raw);
+}
+
+private_signing_key private_signing_key::from_base64(std::string const& base64)
+{
+ private_signing_key ret;
+
+ auto raw = fz::base64_decode(base64);
+ if (raw.size() == key_size) {
+ auto p = reinterpret_cast<uint8_t const*>(&raw[0]);
+ ret.key_.assign(p, p + key_size);
+ }
+
+ return ret;
+}
+
+public_verification_key private_signing_key::pubkey() const
+{
+ public_verification_key ret;
+
+ if (*this) {
+ ret.key_.resize(public_verification_key::key_size);
+ nettle_ed25519_sha512_public_key(ret.key_.data(), key_.data());
+ }
+
+ return ret;
+}
+
+
+std::vector<uint8_t> sign(uint8_t const* message, size_t const size, private_signing_key const& priv)
+{
+ std::vector<uint8_t> ret;
+
+ auto const pub = priv.pubkey();
+ if (priv && pub && size) {
+ ret.reserve(size + signature_size);
+ ret.assign(message, message + size);
+ ret.resize(size + signature_size);
+
+ nettle_ed25519_sha512_sign(pub.key_.data(), priv.data().data(), size, ret.data(), ret.data() + size);
+ }
+
+ return ret;
+}
+
+std::vector<uint8_t> sign(std::vector<uint8_t> const& message, private_signing_key const& priv)
+{
+ return sign(message.data(), message.size(), priv);
+}
+
+std::vector<uint8_t> sign(std::string const& message, private_signing_key const& priv)
+{
+ return sign(reinterpret_cast<uint8_t const*>(message.c_str()), message.size(), priv);
+}
+
+
+// Verify the message. Returns true iff it has been signed by the private key corresponding to the passed public key
+bool verify(uint8_t const* message, size_t const size, public_verification_key const& pub)
+{
+ if (!message || size < signature_size) {
+ return false;
+ }
+ return nettle_ed25519_sha512_verify(pub.key_.data(), size - signature_size, message, message + size - signature_size) == 1;
+}
+
+bool verify(std::vector<uint8_t> const& message, public_verification_key const& pub)
+{
+ return verify(message.data(), message.size(), pub);
+}
+
+bool verify(std::string const& message, public_verification_key const& pub)
+{
+ return verify(reinterpret_cast<uint8_t const*>(message.c_str()), message.size(), pub);
+}
+
+}
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/libfilezilla-0.14.0/tests/Makefile.am new/libfilezilla-0.15.0/tests/Makefile.am
--- old/libfilezilla-0.14.0/tests/Makefile.am 2018-02-23 09:29:01.000000000 +0100
+++ new/libfilezilla-0.15.0/tests/Makefile.am 2018-10-19 12:00:50.000000000 +0200
@@ -5,6 +5,7 @@
test_SOURCES = test.cpp \
buffer.cpp \
+ crypto.cpp \
dispatch.cpp \
eventloop.cpp \
format.cpp \
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/libfilezilla-0.14.0/tests/crypto.cpp new/libfilezilla-0.15.0/tests/crypto.cpp
--- old/libfilezilla-0.14.0/tests/crypto.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new/libfilezilla-0.15.0/tests/crypto.cpp 2018-10-19 12:00:50.000000000 +0200
@@ -0,0 +1,63 @@
+#include "libfilezilla/encryption.hpp"
+#include "libfilezilla/util.hpp"
+
+#include "test_utils.hpp"
+
+#include <string.h>
+
+class crypto_test final : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(crypto_test);
+ CPPUNIT_TEST(test_encryption);
+ CPPUNIT_TEST(test_encryption_with_password);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp() {}
+ void tearDown() {}
+
+ void test_encryption();
+ void test_encryption_with_password();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(crypto_test);
+
+void crypto_test::test_encryption()
+{
+ auto priv = fz::private_key::generate();
+ priv.generate();
+
+ auto const pub = priv.pubkey();
+
+ std::string const plain = "Hello world";
+
+ auto cipher = fz::encrypt(plain, pub);
+ CPPUNIT_ASSERT(fz::decrypt(cipher, priv) == std::vector<uint8_t>(plain.cbegin(), plain.cend()));
+}
+
+
+void crypto_test::test_encryption_with_password()
+{
+ auto const salt = fz::random_bytes(fz::private_key::salt_size);
+
+ std::string const plain = "Hello world";
+ std::vector<uint8_t> cipher;
+
+ {
+ auto priv = fz::private_key::from_password("super secret", salt);
+ CPPUNIT_ASSERT(priv);
+
+ auto const pub = priv.pubkey();
+
+ cipher = fz::encrypt(plain, pub);
+ }
+
+
+ {
+ auto priv = fz::private_key::from_password("super secret", salt);
+ CPPUNIT_ASSERT(priv);
+
+ CPPUNIT_ASSERT(fz::decrypt(cipher, priv) == std::vector<uint8_t>(plain.cbegin(), plain.cend()));
+ }
+
+}
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/libfilezilla-0.14.0/tests/string.cpp new/libfilezilla-0.15.0/tests/string.cpp
--- old/libfilezilla-0.14.0/tests/string.cpp 2018-10-04 13:17:12.000000000 +0200
+++ new/libfilezilla-0.15.0/tests/string.cpp 2018-10-19 12:00:50.000000000 +0200
@@ -99,9 +99,9 @@
CPPUNIT_ASSERT_EQUAL(std::string("Zm9vbA"), fz::base64_encode("fool", fz::base64_type::standard, false));
CPPUNIT_ASSERT_EQUAL(std::string("Zm9vbHM"), fz::base64_encode("fools", fz::base64_type::standard, false));
- CPPUNIT_ASSERT_EQUAL(std::string("AAECA/3+/w=="), fz::base64_encode({0, 1, 2, 3, '\xfd', '\xfe', '\xff'}));
+ CPPUNIT_ASSERT_EQUAL(std::string("AAECA/3+/w=="), fz::base64_encode(std::string({0, 1, 2, 3, '\xfd', '\xfe', '\xff'})));
- CPPUNIT_ASSERT_EQUAL(std::string("AAECA_3-_w=="), fz::base64_encode({0, 1, 2, 3, '\xfd', '\xfe', '\xff'}, fz::base64_type::url));
+ CPPUNIT_ASSERT_EQUAL(std::string("AAECA_3-_w=="), fz::base64_encode(std::string({0, 1, 2, 3, '\xfd', '\xfe', '\xff'}), fz::base64_type::url));
// decode
CPPUNIT_ASSERT_EQUAL(std::string(""), fz::base64_decode(""));
1
0
Hello community,
here is the log from the commit of package filezilla for openSUSE:Factory checked in at 2018-10-29 14:22:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/filezilla (Old)
and /work/SRC/openSUSE:Factory/.filezilla.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "filezilla"
Mon Oct 29 14:22:28 2018 rev:69 rq:645009 version:3.38.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/filezilla/filezilla.changes 2018-10-15 09:48:07.711057509 +0200
+++ /work/SRC/openSUSE:Factory/.filezilla.new/filezilla.changes 2018-10-29 14:58:48.706012090 +0100
@@ -1,0 +2,22 @@
+Sat Oct 27 08:41:32 UTC 2018 - ecsos(a)opensuse.org
+
+- update to 3.38.0
+ * Bugfixes and minor changes:
+ - Updated translations
+- update to 3.38.0-rc1
+ * New features:
+ - Refreshing remote file list while holding Ctrl now clears
+ the remote directory cache for the current server
+ - Changed default logon type if creating a new site in the Site
+ Manager
+ * Bugfixes and minor changes:
+ - Fixed state of controles in the Site Manager when creating
+ a new site after the previously viewed site
+ has been - predefined
+ - Fixed dragging remote files to queue
+ - Building and running FileZilla now depends on
+ libfilezilla >= 0.15.0 (https://lib.filezilla-project.org/)
+ - Improve compatibility with GnuTLS 3.6.x
+ - Fix building with automake >= 1.16.0
+
+-------------------------------------------------------------------
Old:
----
FileZilla_3.37.4_src.tar.bz2
New:
----
FileZilla_3.38.0_src.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ filezilla.spec ++++++
--- /var/tmp/diff_new_pack.KGS1Jg/_old 2018-10-29 14:58:49.306012920 +0100
+++ /var/tmp/diff_new_pack.KGS1Jg/_new 2018-10-29 14:58:49.310012925 +0100
@@ -17,7 +17,7 @@
Name: filezilla
-Version: 3.37.4
+Version: 3.38.0
Release: 0
Summary: A GUI FTP and SFTP Client
License: GPL-2.0-or-later
@@ -38,7 +38,7 @@
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(gnutls) >= 3.4.15
BuildRequires: pkgconfig(gtk+-2.0)
-BuildRequires: pkgconfig(libfilezilla) >= 0.14.0
+BuildRequires: pkgconfig(libfilezilla) >= 0.15.0
BuildRequires: pkgconfig(libidn)
BuildRequires: pkgconfig(nettle) >= 3.1
# filezilla-team use BuildRequires: pkgconfig(sqlite3) >= 3.11.1
++++++ FileZilla_3.37.4_src.tar.bz2 -> FileZilla_3.38.0_src.tar.bz2 ++++++
++++ 93841 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package latte-dock for openSUSE:Factory checked in at 2018-10-29 14:22:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/latte-dock (Old)
and /work/SRC/openSUSE:Factory/.latte-dock.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "latte-dock"
Mon Oct 29 14:22:23 2018 rev:5 rq:644961 version:0.8.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/latte-dock/latte-dock.changes 2018-09-24 13:12:34.305779306 +0200
+++ /work/SRC/openSUSE:Factory/.latte-dock.new/latte-dock.changes 2018-10-29 14:58:43.642004836 +0100
@@ -1,0 +2,15 @@
+Fri Oct 26 20:31:59 UTC 2018 - wbauer(a)tmo.at
+
+- Update to 0.8.2
+ * Fix wrong placement of docks during startup for multi-screen
+ environments
+ * Show explicit docks automatically when their corresponding
+ screen is added in a multi-screen environment
+ * Open files properly when dropping them on launchers
+ * Improve behavior according to Fitt's Law when shrinking panel
+ margins
+ * Don't hide previews when hovering player buttons
+ * Update delete icons to plasma design
+ * Don't break BorderlessMaximized window default value
+
+-------------------------------------------------------------------
Old:
----
latte-dock-0.8.1.tar.xz
New:
----
latte-dock-0.8.2.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ latte-dock.spec ++++++
--- /var/tmp/diff_new_pack.uFKRUI/_old 2018-10-29 14:58:44.054005445 +0100
+++ /var/tmp/diff_new_pack.uFKRUI/_new 2018-10-29 14:58:44.054005445 +0100
@@ -19,7 +19,7 @@
%define kf5_version 5.38.0
Name: latte-dock
-Version: 0.8.1
+Version: 0.8.2
Release: 0
Summary: Task manager
License: GPL-2.0-or-later
++++++ latte-dock-0.8.1.tar.xz -> latte-dock-0.8.2.tar.xz ++++++
++++ 4265 lines of diff (skipped)
1
0