pax_global_header00006660000000000000000000000064132001627200014503gustar00rootroot0000000000000052 comment=66dcdc07085237592c3849e3ffcc63a5c6f49e4d appstream-generator-0.6.8/000077500000000000000000000000001320016272000154765ustar00rootroot00000000000000appstream-generator-0.6.8/.gitignore000066400000000000000000000001121320016272000174600ustar00rootroot00000000000000build/ .dub docs.json dub.selections.json __dummy.html *.o *.obj *.so *.a appstream-generator-0.6.8/.travis.yml000066400000000000000000000005061320016272000176100ustar00rootroot00000000000000# Travis CI config for the AppStream Generator language: d sudo: required dist: trusty services: - docker d: - gdc - ldc matrix: allow_failures: - d: gdc before_script: - docker build -t asgen -f test/ci/Dockerfile . script: - docker run -t -e DC=$DC -v `pwd`:/build asgen ./test/ci/build_and_test.sh appstream-generator-0.6.8/LICENSE000066400000000000000000000167431320016272000165160ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. appstream-generator-0.6.8/MAINTAINERS000066400000000000000000000000471320016272000171740ustar00rootroot00000000000000Matthias Klumpp E-mail: mak@debian.org appstream-generator-0.6.8/NEWS000066400000000000000000000331451320016272000162030ustar00rootroot00000000000000Version 0.6.8 ~~~~~~~~~~~~~~ Released: 2017-11-06 Notes: * The -Ddownload_js build flag is now -Ddownload-js to follow the naming of other Meson flags more closely. Features: * Encode AppStream library version in version info string on reports * Don't require an install candidate for a webapp * Update hicolor theme fallback definition * Try to filter out symbolic icons for apps * Allow processing only one section in a suite * Relax icon scaling rules Bugfixes: * Move time graph legend to the top left * ci: Use the packaged gir-to-d * Drop an unused gdc conditional * Ensure the validator never tests web URLs for validity * Drop LLVM DC bug workaround and allow cross-module inlining * Make D GIR interface build work again with recent Meson versions * Don't fail if we have a dupe ID with no pkgname, can happen now with webapps Version 0.6.7 ~~~~~~~~~~~~~~ Released: 2017-10-02 Features: * ci: Enable gdc again for testing (Matthias Klumpp) * Make rpmmd backend work (Matthias Klumpp) * Make an empty main function for embedded unittests (Matthias Klumpp) * Add a metainfo file (Matthias Klumpp) * Add a manual page (Matthias Klumpp) * Sort suite names on the index page (Matthias Klumpp) Bugfixes: * use file.exists to check file existence (Antonio Rojas) * arch: Don't ref generator results (Matthias Klumpp) * Improve the icon tarball generation code (Matthias Klumpp) * Resolve deprecation warning (Matthias Klumpp) Version 0.6.6 ~~~~~~~~~~~~~~ Released: 2017-09-22 Features: * Add basic HiDPI support (Corentin Noël) * Generate the HiDPI tarball (Corentin Noël) * Add an 'info' command to dump package information (Matthias Klumpp) * Handle the "Hidden" property in .desktop files and complain about it (Matthias Klumpp) Bugfixes: * arch: XML-escape package descriptions (Matthias Klumpp) * Check for availability of a component-id at the right time (Matthias Klumpp) * Make writing compressed results a bit more robust (Matthias Klumpp) * Resolve all deprecation warnings and slightly improve code (Matthias Klumpp) Version 0.6.5 ~~~~~~~~~~~~~~ Released: 2017-07-02 Features: * Generate type=codec metadata for gstreamer packages (Iain Lane) * Add a feature flag for GStreamer processing (Iain Lane) * ci: Switch to using upstream GirToD (Matthias Klumpp) * Set asgen version in defines.d by Meson as well (Matthias Klumpp) * Format graphs a bit nicer (Matthias Klumpp) Bugfixes: * Find files in DATADIR - not relative to the executable (Iain Lane) * Fix typo in metadata-path hint (Matthias Klumpp) * Try to be more informative when a component has no ID (Matthias Klumpp) * Ensure the rDNS scheme is really followed before editing an ID (Matthias Klumpp) Version 0.6.4 ~~~~~~~~~~~~~~ Released: 2017-05-25 Features: * Automatically generate GIR D bindings at build-time (Matthias Klumpp) * Remove dub build file (Matthias Klumpp) * Use Meson subproject/wrap to fetch mustache-d in case it is missing (Matthias Klumpp) * Add a launchable tag to output if we can add one (Matthias Klumpp) * Make legacy metainfo dir a warning (Matthias Klumpp) * Validate launchable entries and add heuristics in case they aren't present (Matthias Klumpp) Bugfixes: * Import buildPath directly from std.path (Antonio Rojas) * Remove spurious std.stream import (Matthias Klumpp) Version 0.6.3 ~~~~~~~~~~~~~~ Released: 2017-03-08 Features: * Experiment with scoped classes (Matthias Klumpp) * Drop embedded generator copy (Matthias Klumpp) * Use final classes whenever possible (Matthias Klumpp) * Centralize all export-dir locations in base config class (Matthias Klumpp) * Allow to manually configure data export locations (Matthias Klumpp) Bugfixes: * Fix some quirks and make the tests work again (Matthias Klumpp) * ci: Don't build with GDC (Matthias Klumpp) * Don't fail if a suite has no base suite (Matthias Klumpp) * engine: Process base suite packages for contents only (Iain Lane) * Update README.md (#39) (Blake Kostner) * debian: Only select the most recent packages for a scan (Matthias Klumpp) * Streamline final component validity check, resolve a crash (Matthias Klumpp) Version 0.6.2 ~~~~~~~~~~~~~~ Released: 2017-01-24 Notes: * GDC 6.x can't compile the project at time due to a GDC bug. See https://bugzilla.gdcproject.org/show_bug.cgi?id=251 for more information. Features: * Support desktop-app metainfo files without .desktop file if they have an icon set * Write log entry when starting/finishing icon tarball write * Update AppStream bindings * Allow to specify allowed keys * Don't show pedantic validator hints * Allow metainfo file to specify sample texts for fonts * Process XPM icons if they are large enough Bugfixes: * Safeguard against TLD checks with empty-or-null string * Ensure desktop-apps have at least one valid category set * Don't override metainfo name/summary with .desktop values * Quit immediately if the component type is unknown * Correctly read a font's full-name * Don't needlessly reprocess fonts Version 0.6.1 ~~~~~~~~~~~~~~ Released: 2016-12-26 Features: * Add a symlink so that Ubuntu uses the same template as Debian (Iain Lane) * Support linking to "old suites" in the HTML index (Iain Lane) * hints: icon-not-found: Explain the symlink problem for Debian & Ubuntu (Iain Lane) * Add preliminary new asgen logo (Matthias Klumpp) * Use struct for archive (Matthias Klumpp) * Reuse AsMetadata while processing metainfo files (Matthias Klumpp) Bugfixes: * Correctly install templates with Meson (Matthias Klumpp) * meson: Make finding mustache-d more robust (Matthias Klumpp) * Fix build with DMD (Antonio Rojas) * engine: Don't clean packages in base suites (Iain Lane) * download: If we have a last-modified date, set the mtime of the target file (Iain Lane) * Simplify zarchive code a little (Matthias Klumpp) * Use module initializer to initialize global static data (Matthias Klumpp) * Fix build on Debian with GDC (Matthias Klumpp) Version 0.6.0 ~~~~~~~~~~~~~~ Released: 2016-10-03 Notes: * If possible, you should build Meson with the LLVM D compiler and the Meson build system now. Features: * Produce better error messages on failed libarchive actions (Matthias Klumpp) * Add a hook to the desktop file parser to run backend specific code (Iain Lane) * Add an Ubuntu backend to retrieve langpack translations (Iain Lane) * Open databases with NOTLS (Matthias Klumpp) * Tweak the issue messages a bit (Matthias Klumpp) * Complain about stuff in legacy paths (Matthias Klumpp) * Only search for .desktop files if we have a DESKTOP_APP component (Matthias Klumpp) * Create new Font class to read font metadata (Matthias Klumpp) * Render an icon for fonts (Matthias Klumpp) * Add dependencies on Pango, FreeType and Fontconfig (Matthias Klumpp) * Determine languages a font supports (Matthias Klumpp) * Reorganize code for proper namespacing (Matthias Klumpp) * Render font screenshots (Matthias Klumpp) * Map font full names to files in a spec-compliant way (Matthias Klumpp) * Enable fonts support by default (Matthias Klumpp) * Share ContentsStore between threads again (Matthias Klumpp) * Make Meson a first-class buildsystem for asgen (Matthias Klumpp) * Update README (Matthias Klumpp) Bugfixes: * Fix build on non-64-bit architectures (Matthias Klumpp) * Work around LDC bug (Matthias Klumpp) * fclose() the memstream when we are done with it (Iain Lane) * debpkgindex: Be less noisy about translations in debug mode (Iain Lane) * Use getTestSamplesDir (Iain Lane) * Retry on all curl errors, not just timeouts (Iain Lane) * Synchronise downloading of files (Iain Lane) * ubuntu: Don't reference all packages, just the ones we need (langpacks) (Iain Lane) * Use an ugly mutex to work around Fontconfig issues (Matthias Klumpp) * Make FC mutex a bit more fine-grained (Matthias Klumpp) Version 0.5.0 ~~~~~~~~~~~~~~ Released: 2016-08-30 Features: * Add more speed and style optimizations, make Package an abstract class (Matthias Klumpp) * Use a string appender instead of a string array for writing output (Matthias Klumpp) * debian: Support downloading files from a mirror, instead of having them local (Iain Lane) * debian: Support DDTP translations (Iain Lane) * Ignore some more useless categories (Matthias Klumpp) * Add skeleton for RPMMD (Matthias Klumpp) * Add a few optimizations using immutable and appender (Matthias Klumpp) * Do not spawn compressors anymore, use libarchive directly (Matthias Klumpp) * Make compiling with LDC easier (Matthias Klumpp) * Add example for cruft collection script (Matthias Klumpp) * Allow cleaning up statistical data retroactively (Matthias Klumpp) * Rehash hash tables that we query often (Matthias Klumpp) * Always optimize debug builds (Matthias Klumpp) * Make a splitbuild with Meson and Ninja possible (Matthias Klumpp) * Use AppStream's knowledge about TLDs to build smarter global-component-ids (Matthias Klumpp) * Allow specifying the format version metadata should be built for (Matthias Klumpp) * Adjust for AppStream 0.10 release (Matthias Klumpp) * Perform legal checks before allowing metadata to be added to the pool (Matthias Klumpp) Bugfixes: * Fix dataUseJSTime in section overview template (Blake Kostner) * debian: Only retrieve DDTP translations from the section we're looking at (Iain Lane) * Fix deprecation warnings from LDC (Matthias Klumpp) * Work around some weird JSON parser quirk (int incompatible with uint) (Matthias Klumpp) * Prevent creating excess statistic entries (Matthias Klumpp) * Fix potential crash (Matthias Klumpp) * Use native generator when not compiling with GDC (Matthias Klumpp) * Work correctly if CIDs omit the .desktop suffix (Matthias Klumpp) * Only add valid category names to output (Matthias Klumpp) * Don't emit description-from-package multiple times per package. (Matthias Klumpp) Version 0.4.0 ~~~~~~~~~~~~~~ Released: 2016-07-12 Features: * README: Add link to D tour * Run optipng with standard settings * Add command to forget extracted data for a package * Implement immutable suites * Use appender more often and apply some style fixes * Build with parallel by default when using Makefile * Drop some deprecated stuff Bugfixes: * Display an error when processing a suite without section or arch * debian: Fix exception message if directory does not exist * Code improvements: More pure, more safe, more trusted * Drop global data validation result box * Don't crash if media pool directory does not exist and immutable suites are used Version 0.3.0 ~~~~~~~~~~~~~~ Released: 2016-05-24 Features: * Register new backend for Arch Linux (Matthias Klumpp) * arch: Add reader for lists index file and skeleton for PackageIndex (Matthias Klumpp) * Make generic archive class work well with non-Debian packages (Matthias Klumpp) * Add HTML anchors for maintainers on report pages (Matthias Klumpp) * html: Show suite name in section overview (Matthias Klumpp) * Allow not setting a MediaBaseUrl (Matthias Klumpp) * Add some font rendering experiments (Matthias Klumpp) * Allow storing multiple statitics entries per point in time (Matthias Klumpp) * Make icon tarball build reproducible (Matthias Klumpp) * Make ArchiveDecompressor API more powerful and always return const(ubyte)[] (Matthias Klumpp) * arch: Speed up backend by loading all data in one go (Matthias Klumpp) * Split "handleScreenshots" into more useful, fine-grained flags (Matthias Klumpp) * Add timestamp to output and only touch it if something has changed (Matthias Klumpp) * Only update metadata if the indices have been changed (Matthias Klumpp) * Store media in pool subdirectory (Matthias Klumpp) * Add flag to enforce metadata processing, even if nothing changed (Matthias Klumpp) * Allow disabling metadata timestamps (Matthias Klumpp) * Improve scan-skipping code (Matthias Klumpp) Bugfixes: * Fix build on non-64bit arches (Matthias Klumpp) * Handle compressed empty files correctly (Neil Mayhew) * Drop other, non-UTF-8 encodings from language codes too (Matthias Klumpp) * Drop non-printable characters from .desktop file values (Matthias Klumpp) * Loop over more things by-reference to reduce RAM usage (Matthias Klumpp) * debian: Read Packages.xz files if no .gz file is available (Matthias Klumpp) * Don't lie about thumbnail sizes in their filename (Matthias Klumpp) * Don't duplicate architecture tag if there are multiple issues (Matthias Klumpp) * Catch data serialization errors (Matthias Klumpp) * Run bower with allow root to be able to make js as root (Harald Sitter) Version 0.2.0 ~~~~~~~~~~~~~~ Released: 2016-04-24 Features: * Don't ship minified JS * Get rid of (almost) all the embedded JS copies, use Bower * Add makefile for convenience * Use Flot for drawing graphs * Update README * Document all asgen-config settings * Reserve subdb in contents database to cache icon data * Make IconHandler use a pre-filtered list of icons * Allow templates to override only parts of the default branding * Add some default branding for Debian * Show logo on generated HTML pages * debian: Link some interesting resources from the main page Bugfixes: * Find aliased icons correctly * Keep priority sorting of themes * Make the hicolor theme always-available, using an embedded index copy if necessary * Fix counting of issues * Do not accidentally upscale screenshots while creating thumbnails * debian: Don't make a missing package index fatal * Don't fail if we are trying to add statistics too quickly * Rename remove-valid to reflect what it actually does * Ignore errors if we are trying to decompress a 0-byte gzip file * Suite arguments aren't optional for process/remove-found * Demote screenshot-no-thumbnails to info Version 0.1.0 ~~~~~~~~~~~~~~ Released: 2016-04-18 Notes: * Initial release appstream-generator-0.6.8/README.md000066400000000000000000000057211320016272000167620ustar00rootroot00000000000000# AppStream Generator AppStream is an effort to provide additional metadata and unique IDs for all software available in a Linux system. This repository contains the server-side of the AppStream infrastructure, a tool to generate metadata from distribution packages. You can find out more about AppStream collection metadata at [Freedesktop](https://www.freedesktop.org/software/appstream/docs/chap-CollectionData.html). The AppStream generator is currently primarily used by Debian, but is written in a distribution agnostic way. Backends only need to implement [two interfaces](src/asgen/backends/interfaces.d) to to be ready. If you are looking for the AppStream client-tools, the [AppStream repository](https://github.com/ximion/appstream) is where you want to go. ![AppStream Generator Logo](data/templates/default/static/img/asgen.png "AppStream Generator") ## Development [![Build Status](https://travis-ci.org/ximion/appstream-generator.svg?branch=master)](https://travis-ci.org/ximion/appstream-generator) ### Build dependencies * LDC[1] * Meson (>= 0.34) [2] * glib2 (>= 2.46) * AppStream [3] * libarchive (>= 3.2) [4] * LMDB [5] * mustache-d [6] * GirToD [7] * Cairo * GdkPixbuf 2.0 * RSvg 2.0 * FreeType * Fontconfig * Pango * Bower (optional) [8] [1]: https://github.com/ldc-developers/ldc/releases [2]: http://mesonbuild.com/ [3]: https://github.com/ximion/appstream [4]: http://www.libarchive.org/ [5]: http://symas.com/mdb/ [6]: https://github.com/repeatedly/mustache-d [7]: https://github.com/gtkd-developers/GIR-D-Generator [8]: http://bower.io/ On Debian and derivatives of it, all build requirements can be installed using the following command: ```ShellSession sudo apt install meson ldc gir-to-d libappstream-dev libgdk-pixbuf2.0-dev libarchive-dev \ librsvg2-dev liblmdb-dev libglib2.0-dev libcairo2-dev libcurl4-gnutls-dev \ libfreetype6-dev libfontconfig1-dev libpango1.0-dev libmustache-d-dev ``` ### Build instructions To build the tool with Meson, create a `build` subdirectory, change into it and run `meson .. && ninja` to build. In summary: ```ShellSession $ mkdir build && cd build $ meson -Ddownload-js=true .. $ ninja $ sudo ninja install ``` We support several options to be set to influence the build. Change into the build directory and run `mesonconf` to see them all. You might want to perform an optimized debug build by passing `--buildtype=debugoptimized` to `meson` or just do a release build straight away with `--buildtype=release` in case you want to use the resulting binaries productively. By default, the build happens without optimizations which slows down the generator. ## Usage Take a look at the `docs/` directory in the source tree for information on how to use the generator and write configuration files for it. ## Hacking Pull-requests and patches are very welcome! If you are new to D, it is highly recommended to take a few minutes to look at the D tour to get a feeling of what the language can do: http://tour.dlang.org/ appstream-generator-0.6.8/RELEASE000066400000000000000000000016211320016272000165010ustar00rootroot00000000000000AppStream Generator Release Notes 1. Write NEWS entries for AppStream Generator in the same format as usual. git shortlog v0.6.7.. | grep -i -v trivial | grep -v Merge > NEWS.new -------------------------------------------------------------------------------- Version 0.6.8 ~~~~~~~~~~~~~~ Released: 2017-xx-xx Notes: Features: Bugfixes: -------------------------------------------------------------------------------- 2. Commit changes in Git: git commit -a -m "Release version 0.6.8" git tag -s -f -m "Release 0.6.8" v0.6.8 git push --tags git push 3. Do post release version bump in meson.build, RELEASE 4. Commit trivial changes: git commit -a -m "trivial: post release version bump" git push 5. Send an email to appstream@lists.freedesktop.org ================================================= AppStream Generator 0.6.8 released! ================================================= appstream-generator-0.6.8/TODO000066400000000000000000000005071320016272000161700ustar00rootroot00000000000000= AppStream Generator TODO List = === Known issues === * No persistent problems at time :-) === Planned Features === * Extract localization status for AppStream components and add them as `Languages` field. === Whishlist / Random Ideas === * Add an icon-cache so we don't render SVG icons in themes multiple times. appstream-generator-0.6.8/contrib/000077500000000000000000000000001320016272000171365ustar00rootroot00000000000000appstream-generator-0.6.8/contrib/cleanup-cruft.sh.example000066400000000000000000000013511320016272000236740ustar00rootroot00000000000000#!/bin/bash # # Script cleaning up the AppStream metadata pool and cache. # This script should be run by a cronjob (e.g. every week). # set -e set -o pipefail set -u WORKSPACE_DIR="/srv/appstream/workspace" # only run one instance of the script LOCKFILE="$WORKSPACE_DIR/.lock" cleanup() { rm -f "$LOCKFILE" } if ! lockfile -r8 $LOCKFILE; then echo "aborting AppStream metadata cleanup because $LOCKFILE has already been locked" exit 0 fi trap cleanup 0 # Start logging logdir="$WORKSPACE_DIR/logs/`date "+%Y/%m"`" mkdir -p $logdir NOW=`date "+%d_%H%M"` LOGFILE="$logdir/${NOW}_cleanup.log" exec >> "$LOGFILE" 2>&1 cd $WORKSPACE_DIR # Cleanup superseded data appstream-generator cleanup # finish logging exec > /dev/null 2>&1 appstream-generator-0.6.8/contrib/girwrap/000077500000000000000000000000001320016272000206115ustar00rootroot00000000000000appstream-generator-0.6.8/contrib/girwrap/APILookup.txt000066400000000000000000000064171320016272000231650ustar00rootroot00000000000000# # Licensed under the GNU Lesser General Public License Version 3 # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the license, or # (at your option) any later version. # # This software 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library. If not, see . # define the license to use license: start /* * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ // generated automatically - do not change license: end includeComments: y # defines the simple token substitution # TODO allow to create real aliases on the code and simple static token replacement alias: volatile alias: G_CONST_RETURN alias: gint int alias: guint uint alias: gboolean bool alias: gpointer void* alias: gconstpointer void* alias: gchar char alias: guchar char alias: gshort short alias: gushort ushort alias: gint8 byte alias: guint8 ubyte alias: gint16 short alias: guint16 ushort alias: gint32 int alias: gint64 long alias: guint32 uint alias: guint64 ulong alias: guintptr size_t alias: gfloat float alias: gdouble double alias: goffset long alias: gsize size_t alias: gssize ptrdiff_t alias: va_list void* alias: unichar dchar alias: unichar2 wchar alias: uchar ubyte alias: XID uint alias: gunichar dchar alias: gunichar2 wchar alias: time_t uint alias: uid_t uid_t alias: alias alias_ alias: align alig alias: body bod alias: continue continu alias: debug dbg alias: default defaulx alias: delete delet alias: export expor alias: foreach foreac alias: function funct alias: Function Funct alias: in inn alias: instance instanc alias: interface iface alias: module modul alias: out output alias: package p alias: ref doref alias: scope scop alias: string str alias: switch switc alias: union unio alias: version versio alias: GLIB_SYSDEF_POLLIN =1 alias: GLIB_SYSDEF_POLLOUT =4 alias: GLIB_SYSDEF_POLLPRI =2 alias: GLIB_SYSDEF_POLLHUP =16 alias: GLIB_SYSDEF_POLLERR =8 alias: GLIB_SYSDEF_POLLNVAL =32 ########################################################### ### predifined: lib ########################################################### srcDir: . lookup: APILookupAppStream.txt lookup: APILookupGLib.txt lookup: APILookupGObject.txt lookup: APILookupGio.txt #lookup: APILookupGdkPixbuf.txt appstream-generator-0.6.8/contrib/girwrap/APILookupAppStream.txt000066400000000000000000000021411320016272000247700ustar00rootroot00000000000000# # Licensed under the GNU Lesser General Public License Version 3 # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the license, or # (at your option) any later version. # # This software 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library. If not, see . ############################################# ### Definitions for wrapping Gtk+ ########### ############################################# # must start with wrap wrap: appstream file: AppStream-1.0.gir addAliases: start public import glib.c.types; public import gobject.c.types; public import gio.c.types; public import core.stdc.stdio; public import core.stdc.string; addAliases: end appstream-generator-0.6.8/contrib/girwrap/APILookupGLib.txt000066400000000000000000001274331320016272000237250ustar00rootroot00000000000000# # Licensed under the GNU Lesser General Public License Version 3 # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the license, or # (at your option) any later version. # # This software 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library. If not, see . ############################################# ### Definitions for wrapping Gtk+ ########### ############################################# # must start with wrap wrap: glib file: GLib-2.0.gir file: GModule-2.0.gir addAliases: start public alias uint uid_t; public alias int pid_t; version( Windows ) { alias int glong; alias uint gulong; } else version( X86_64 ) { alias long glong; alias ulong gulong; } else { alias int glong; alias uint gulong; } version( Windows ) enum _utfPostfix = "_utf8"; else enum _utfPostfix = ""; version (Windows) { private import core.stdc.stdio; static if( !is(typeof(fdopen(0, null))) ) { extern (C) FILE* fdopen(int, char*); } } static if ( __VERSION__ >= 2063 ) { public import std.typecons : scoped; template Scoped(T) { alias typeof(scoped!T(cast(typeof(T.tupleof[0]))null)) Scoped; } } else { // I'm getting the following error on the older dmd versions: // this for Scoped_store needs to be type Scoped not type inout(Scoped!(T)). // Unlike the phobos version this does use GC alocated memory for the object. // Within GtkD this is used to make sure destroy is called on the object // so it releases the resources it holds. struct Scoped(T) { T payload; alias payload this; @disable this(); @disable this(this); ~this() { .destroy(payload); } } auto scoped(T, Args...)(auto ref Args args) if (is(T == class)) { Scoped!(T) result = void; result.payload = new T(args); return result; } } /** * Get the length of a zero terminated array. */ size_t getArrayLength(T)(T* arr) { size_t len; for ( ; arr[len]; len++ ){} return len; } unittest { assert(getArrayLength("aaaaaaaaa\0".ptr) == 9); } Type* gMalloc(Type)() { import glib.c.functions; return cast(Type*)g_malloc0(Type.sizeof); } alias void* GIConv; addAliases: end addEnums: start enum GPriority { HIGH = -100, DEFAULT = 0, HIGH_IDLE = 100, DEFAULT_IDLE = 200, LOW = 300 } addEnums: end struct: Array class: ArrayG struct: Base64 move: base64_decode_step Base64 decode_step move: base64_decode_inplace Base64 decode_inplace noCode: decode_step array: decode_inplace Return out_len code: start /** * Incrementally decode a sequence of binary data from its Base-64 stringified * representation. By calling this function multiple times you can convert * data in chunks to avoid having to have the full encoded data in memory. * * The output buffer must be large enough to fit all the data that will * be written to it. Since base64 encodes 3 bytes in 4 chars you need * at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero * state). * * Params: * inn = binary input data * len = max length of @in data to decode * output = output buffer * state = Saved state between steps, initialize to 0 * save = Saved state between steps, initialize to 0 * * Return: The number of bytes of output that was written * * Since: 2.12 */ public static size_t decodeStep(string inn, ref ubyte[] output, ref int state, ref uint save) { auto p = g_base64_decode_step(Str.toStringz(inn), cast(int)inn.length, cast(char*)output.ptr, &state, &save); return p; } code: end struct: BookmarkFile out: load_from_data_dirs full_path array: set_groups groups length struct: ByteArray class: ByteArray struct: Bytes noCode: new_take noCode: new_static struct: Checksum noCode: get_digest code: start /** * Gets the digest from checksum as a raw binary vector and places it * into buffer. The size of the digest depends on the type of checksum. * * Once this function has been called, the Checksum is closed and can * no longer be updated with update(). * * Params: * buffer = output buffer * digestLen = an inout parameter. The caller initializes it to the size of buffer. * After the call it contains the length of the digest. * * Since: 2.16 */ public void getDigest(ref ubyte[] buffer) { size_t digestLen = buffer.length; g_checksum_get_digest(gChecksum, buffer.ptr, &digestLen); buffer = buffer[0 .. digestLen]; } code: end struct: ConstructionException namespace: code: start class ConstructionException : Exception { this(string message) { super(message); } override string toString() { return "Construction failure, " ~ msg; } } code: end struct: DateTime structWrap: gpointer DateTime noCode: new_now_utc noCode: new_now_local noCode: new_from_unix_local noCode: new_from_unix_utc noCode: new_from_timeval_local noCode: new_from_timeval_utc noCode: new_local noCode: new_utc noCode: hash code: start /** * Creates a DateTime corresponding to the given Unix time t * Unix time is the number of seconds that have elapsed since 1970-01-01 * 00:00:00 UTC, regardless of the local time offset. * * This call can fail (ConstructionException) if t represents a time outside * of the supported range of GDateTime. * You should release the return value by calling unref() * when you are done with it * * Params: * t = the Unix time * utc = If true use utc else use the local timezone. * * Throws: ConstructionException GTK+ fails to create the object. * * Since: 2.26 */ public this (long t, bool utc = true) { GDateTime* p; if ( utc ) { p = g_date_time_new_from_unix_utc(t); } else { p = g_date_time_new_from_unix_local(t); } if(p is null) { throw new ConstructionException("null returned by g_date_time_new_from_unix_local(t)"); } this(cast(GDateTime*) p); } /** * Creates a DateTime corresponding to the given TimeVal tv. * The time contained in a TimeVal is always stored in the form of * seconds elapsed since 1970-01-01 00:00:00 UTC, regardless of the * local time offset. * * This call can fail (ConstructionException) if tv represents a time outside * of the supported range of DateTime. * You should release the return value by calling unref() * when you are done with it. * * Params: * tv = a GTimeVal * utc = If true use utc else use the local timezone. * * Throws: ConstructionException GTK+ fails to create the object. * * Since: 2.26 */ public this (ref GTimeVal tv, bool utc = true) { GDateTime* p; if ( utc ) { p = g_date_time_new_from_timeval_utc(&tv); } else { p = g_date_time_new_from_timeval_local(&tv); } if(p is null) { throw new ConstructionException("null returned by g_date_time_new_from_timeval_local((tv is null) ? null : tv.getTimeValStruct())"); } this(cast(GDateTime*) p); } /** */ override bool opEquals(Object rhs) { DateTime date = cast(DateTime)rhs; if ( date is null ) return false; return equal(this, date) != 0; } /** */ override int opCmp(Object rhs) { DateTime date = cast(DateTime)rhs; if ( date is null ) return int.min; return compare(this, date); } /** */ override nothrow @trusted hash_t toHash() { return hash(); } /** * Hashes datetime into a guint, suitable for use within GHashTable. * Since 2.26 * Params: * datetime = a GDateTime * Returns: a guint containing the hash */ public nothrow @trusted uint hash() { try { return g_date_time_hash(gDateTime); } catch(Exception e) { return 0; } } code: end struct: Dir class: Directory struct: Error class: ErrorG move: propagate_error Error move: set_error_literal Error out: set_error_literal err out: propagate_error dest struct: GException namespace: import: glib.ErrorG import: glib.Str code: start class GException : Exception { ErrorG error; this(ErrorG error) { super( Str.toString(error.getErrorGStruct().message) ); this.error = error; } } code: end struct: GLib namespace: code: start static import glib.Version; deprecated("moves to the glib.Version module") alias glib.Version.Version Version; code: end struct: HashTable class: HashTable struct: Hmac noCode: get_digest move: compute_hmac_for_data Hmac move: compute_hmac_for_string Hmac array: compute_hmac_for_data data length array: compute_hmac_for_string str length code: start /** * Gets the digest from checksum as a raw binary array and places it * into buffer. The size of the digest depends on the type of checksum. * * Once this function has been called, the Hmac is closed and can * no longer be updated with update(). * * Params: * buffer = output buffer * * Since: 2.30 */ public void getDigest(ref ubyte[] buffer) { size_t digestLen = buffer.length; g_hmac_get_digest(gHmac, buffer.ptr, &digestLen); buffer = buffer[0 .. digestLen]; } code: end struct: IConv namespace: noStruct: true ref: iconv inbuf out: iconv inbytes_left array: iconv inbuf inbytes_left ref: iconv outbuf out: iconv outbytes_left array: iconv outbuf outbytes_left struct: Idle class: Idle cType: code: start /** Holds all idle delegates */ bool delegate()[] idleListeners; /** our idle ID */ uint idleID; /** * Creates a new idle cycle. * Params: * interval = the idle in milieconds * dlg = the delegate to be executed * fireNow = When true the delegate will be executed emmidiatly */ this(bool delegate() dlg, bool fireNow=false) { idleListeners ~= dlg; idleID = g_idle_add(cast(GSourceFunc)&idleCallback, cast(void*)this); if ( fireNow ) { if ( !dlg() ) { idleListeners.length = 0; } } } /** * Creates a new idle cycle. * Params: * dlg = the delegate to be executed * priority = Priority for the idle function * fireNow = When true the delegate will be executed emmidiatly */ this(bool delegate() dlg, GPriority priority, bool fireNow=false) { idleListeners ~= dlg; idleID = g_idle_add_full(priority, cast(GSourceFunc)&idleCallback, cast(void*)this, null); if ( fireNow ) { if ( !dlg() ) { idleListeners.length = 0; } } } /** */ public void stop() { if ( idleID > 0 ) { g_source_remove(idleID); } idleListeners.length = 0; } /** * Removes the idle from gtk */ ~this() { stop(); } /** * Adds a new delegate to this idle cycle * Params: * dlg = * fireNow = */ public void addListener(bool delegate() dlg, bool fireNow=false) { idleListeners ~= dlg; if ( fireNow ) { if ( !dlg() ) { idleListeners.length = idleListeners.length - 1; } } } /** * The callback execution from glib * Params: * idle = * Returns: */ extern(C) static bool idleCallback(Idle idle) { return idle.callAllListeners(); } /** * Executes all delegates on the execution list * Returns: */ private bool callAllListeners() { bool runAgain = false; int i = 0; while ( i 0 ) --l; return line[0..l]; } extern(C) static void childWatchCallback(int pid, int status, Spawn spawn) { //writefln("Spawn.childWatchCallback %s %s", pid, status); spawn.exitStatus = status; if ( spawn.externalWatch !is null ) { spawn.externalWatch(spawn); } spawn.close(); } public bool endOfOutput() { if ( standardOutput is null ) return true; return feof(standardOutput) != 0; } public bool endOfError() { if ( standardError is null ) return true; return feof(standardError) != 0; } string getOutputString() { return Str.toString(strOutput); } string getErrorString() { return Str.toString(strError); } int getExitStatus() { return exitStatus; } /** * Executes a command synchronasly and * optionally calls delegates for sysout, syserr and end of job * */ public int commandLineSync( ChildWatch externalWatch = null, bool delegate(string) readOutput = null, bool delegate(string) readError = null ) { string commandLine; foreach ( int count, string arg; argv) { if ( count > 0 ) { commandLine ~= ' '; } commandLine ~= arg; } int status = g_spawn_command_line_sync( Str.toStringz(commandLine), &strOutput, &strError, &exitStatus, &error); if ( readOutput != null ) { foreach ( string line ; splitLines(Str.toString(strOutput)) ) { readOutput(line); } } if ( readError != null ) { foreach ( string line ; splitLines(Str.toString(strError)) ) { readError(line); } } if ( externalWatch != null ) { externalWatch(this); } return status; } code: end struct: Str import: core.stdc.stdio import: core.stdc.string import: gobject.c.types code: start /* * Convert C-style 0 terminated string s to char[] string. * copied from phobos */ public static string toString(const(char)* s, size_t len = 0) { if ( s is null ) return cast(string)null; if ( len == 0 ) len = strlen(s); return s[0 .. len].idup; } /* * Convert array of chars s[] to a C-style 0 terminated string. * copied from phobos */ public static char* toStringz(string s) { if ( s is null ) return null; char[] copy; if (s.length == 0) { copy = "\0".dup; } else { // Need to make a copy copy = new char[s.length + 1]; copy[0..s.length] = s[]; copy[s.length] = 0; } return copy.ptr; } /** */ public static char** toStringzArray(string[] args) { if ( args is null ) { return null; } char** argv = (new char*[args.length]).ptr; int argc = 0; foreach (string p; args) { argv[argc++] = cast(char*)(p.dup~'\0'); } argv[argc] = null; return argv; } /** */ public static char*** toStringzArray(string[][] args) { if ( args is null ) { return null; } char**[] argv = new char**[args.length]; int argc = 0; foreach( string[] p; args ) { argv[argc++] = toStringzArray(p); } argv[argc] = null; return argv.ptr; } /** */ public static string[] toStringArray(const(char*)* args) { if ( args is null ) { return null; } string[] argv; while ( *args !is null ) { argv ~= toString(*args); args++; } return argv; } /** */ public static string[] toStringArray(const(char*)* args, size_t len) { string[] argv = new string[len]; for ( int i; i < len; i++ ) { argv[i] = toString(args[i]); } return argv; } /** */ public static string[][] toStringArray(char*** args) { string[][] argv; if ( args is null ) { return null; } while ( *args !is null ) { argv ~= toStringArray(*args); args++; } return argv; } /** */ public static void freeString(char* str) { g_free(str); } /** */ public static void freeStringArray(char** str) { g_strfreev(str); } /** */ public static void freeStringArray(char*** str) { while ( *str !is null ) { g_strfreev(*str); str++; } g_free(str); } code: end struct: String class: StringG struct: Thread noCode: new struct: Timeout class: Timeout cType: code: start /** Holds all timeout delegates */ bool delegate()[] timeoutListeners; /** our gtk timeout ID */ uint timeoutID; /** * Creates a new timeout cycle with the default priority, GPriority.DEFAULT. * * Note that timeout functions may be delayed, due to the processing of other * event sources. Thus they should not be relied on for precise timing. * After each call to the timeout function, the time of the next timeout is * recalculated based on the current time and the given interval * (it does not try to 'catch up' time lost in delays). * Params: * interval = the timeout in milieconds * delegate() = the delegate to be executed * fireNow = When true the delegate will be executed emmidiatly */ this(uint interval, bool delegate() dlg, bool fireNow=false) { timeoutListeners ~= dlg; timeoutID = g_timeout_add(interval, cast(GSourceFunc)&timeoutCallback, cast(void*)this); if ( fireNow ) { if ( !dlg() ) { timeoutListeners.length = 0; } } } /** * Creates a new timeout cycle. * Params: * interval = the timeout in milieconds * delegate() = the delegate to be executed * priority = Priority for the timeout function * fireNow = When true the delegate will be executed emmidiatly */ this(uint interval, bool delegate() dlg, GPriority priority, bool fireNow=false) { timeoutListeners ~= dlg; timeoutID = g_timeout_add_full(priority, interval, cast(GSourceFunc)&timeoutCallback, cast(void*)this, null); if ( fireNow ) { if ( !dlg() ) { timeoutListeners.length = 0; } } } /** * Creates a new timeout cycle with the default priority, GPriority.DEFAULT. * Params: * delegate() = the delegate to be executed * seconds = interval in seconds. * fireNow = When true the delegate will be executed emmidiatly */ this(bool delegate() dlg, uint seconds, bool fireNow=false) { timeoutListeners ~= dlg; timeoutID = g_timeout_add_seconds(seconds, cast(GSourceFunc)&timeoutCallback, cast(void*)this); if ( fireNow ) { if ( !dlg() ) { timeoutListeners.length = 0; } } } /** * Creates a new timeout cycle. * Params: * delegate() = the delegate to be executed * seconds = interval in seconds. * priority = Priority for the timeout function * fireNow = When true the delegate will be executed emmidiatly */ this(bool delegate() dlg, uint seconds, GPriority priority, bool fireNow=false) { timeoutListeners ~= dlg; timeoutID = g_timeout_add_seconds_full(priority, seconds, cast(GSourceFunc)&timeoutCallback, cast(void*)this, null); if ( fireNow ) { if ( !dlg() ) { timeoutListeners.length = 0; } } } /** */ public void stop() { if ( timeoutID > 0 ) { g_source_remove(timeoutID); } timeoutID = 0; timeoutListeners.length = 0; } /** * Removes the timeout from gtk */ ~this() { stop(); } /** * Adds a new delegate to this timeout cycle * Params: * dlg = * fireNow = */ public void addListener(bool delegate() dlg, bool fireNow=false) { timeoutListeners ~= dlg; if ( fireNow ) { if ( !dlg() ) { timeoutListeners.length = timeoutListeners.length - 1; } } } /** * The callback execution from glib * Params: * timeout = * Returns: */ extern(C) static bool timeoutCallback(Timeout timeout) { return timeout.callAllListeners(); } /** * Executes all delegates on the execution list * Returns: */ private bool callAllListeners() { bool runAgain = false; int i = 0; while ( i. ############################################# ### Definitions for wrapping Gtk+ ########### ############################################# # must start with wrap wrap: gobject file: GObject-2.0.gir addAliases: start public import glib.c.types; addAliases: end noAlias: Type addEnums: start /** * A value which represents the unique identifier of a registered type. */ enum GType : size_t { INVALID = 0<<2, NONE = 1<<2, INTERFACE = 2<<2, CHAR = 3<<2, UCHAR = 4<<2, BOOLEAN = 5<<2, INT = 6<<2, UINT = 7<<2, LONG = 8<<2, ULONG = 9<<2, INT64 = 10<<2, UINT64 = 11<<2, ENUM = 12<<2, FLAGS = 13<<2, FLOAT = 14<<2, DOUBLE = 15<<2, STRING = 16<<2, POINTER = 17<<2, BOXED = 18<<2, PARAM = 19<<2, OBJECT = 20<<2, VARIANT = 21<<2, } addEnums: end struct: CClosure class: CClosure import: glib.ConstructionException import: gobject.ObjectG noCode: new noCode: new_swap noCode: new_object noCode: new_object_swap code: start /** * Creates a new closure which invokes callbackFunc with userData as * the last parameter. * * Params: * callbackFunc = the function to invoke * userData = user data to pass to callbackFunc * destroyData = destroy notify to be called when userData is no longer used * swap = if true invoce with usrData as the first parameter * * Throws: ConstructionException GTK+ fails to create the object. */ public this(GCallback callbackFunc, void* userData, GClosureNotify destroyData, bool swap) { GClosure* p; if ( swap ) p = g_cclosure_new_swap(callbackFunc, userData, destroyData); else p = g_cclosure_new(callbackFunc, userData, destroyData); if(p is null) { throw new ConstructionException("null returned by new"); } this(cast(GCClosure*) p); } /** * A variant of this() which uses object as userData and * calls ObjectG.watchClosure() on object and the created * closure. This function is useful when you have a callback closely * associated with a gobject.ObjectG, and want the callback to no longer run * after the object is is freed. * * Params: * callbackFunc = the function to invoke * object = a gobject.ObjectG.ObjectG to pass to callbackFunc * swap = if true invoce with usrData as the first parameter * * Throws: ConstructionException GTK+ fails to create the object. */ public this(GCallback callbackFunc, ObjectG object, bool swap) { GClosure* p; if ( swap ) p = g_cclosure_new_object_swap(callbackFunc, (object is null) ? null : object.getObjectGStruct()); else p = g_cclosure_new_object(callbackFunc, (object is null) ? null : object.getObjectGStruct()); if(p is null) { throw new ConstructionException("null returned by new_object"); } this(cast(GCClosure*) p); } code: end struct: Object class: ObjectG import: core.memory import: gobject.Signals merge: InitiallyUnowned noSignal: notify move: clear_object Object inout: clear_object object_ptr code: start protected bool isGcRoot; /** * Sets our main struct and passes store it on the gobject. * Add a gabage collector root to the gtk+ struct so it doesn't get collect */ public this (GObject* gObject, bool ownedRef = false) { this.gObject = gObject; if ( gObject !is null ) { setDataFull("GObject", cast(void*)this, cast(GDestroyNotify)&destroyNotify); addToggleRef(cast(GToggleNotify)&toggleNotify, cast(void*)this); //If the refCount is larger then 1 toggleNotify isn't called if (gObject.refCount > 1 && !isGcRoot) { GC.addRoot(cast(void*)this); isGcRoot = true; } //Remove the floating reference if there is one. if ( isFloating() ) { refSink(); unref(); } //If we already owned this reference remove the one added by addToggleRef. else if ( ownedRef ) { unref(); } //When constructed via GtkBuilder set the structs. if ( getStruct() is null) { setStruct(gObject); } } } extern(C) { static void destroyNotify(ObjectG obj) { if ( obj.isGcRoot ) { GC.removeRoot(cast(void*)obj); obj.isGcRoot = false; } obj.gObject = null; } static void toggleNotify(ObjectG obj, GObject* object, int isLastRef) { if ( isLastRef && obj.isGcRoot ) { GC.removeRoot(cast(void*)obj); obj.isGcRoot = false; } else if ( !obj.isGcRoot ) { GC.addRoot(cast(void*)obj); obj.isGcRoot = true; } } } ~this() { if ( gObject !is null ) { // Remove the GDestroyNotify callback, // for when the D object is destroyed before the C one. g_object_steal_data(gObject, cast(char*)"GObject"); if ( isGcRoot ) { GC.removeRoot(cast(void*)this); isGcRoot = false; } unref(); } } /** * Gets a D Object from the objects table of associations. * Params: * obj = GObject containing the associations. * Returns: the D Object if found, or a newly constructed object if no such Object exists. */ public static RT getDObject(T, RT=T, U)(U obj, bool ownedRef = false) { if ( obj is null ) { return null; } static if ( is(T : ObjectG) ) { auto p = g_object_get_data(cast(GObject*)obj, Str.toStringz("GObject")); if ( p !is null ) { static if ( is(RT == interface ) ) { return cast(RT)cast(ObjectG)p; } else { return cast(RT)p; } } else { return new T(obj, ownedRef); } } else { return new T(obj); } } protected void setStruct(GObject* obj) { gObject = cast(GObject*)obj; } /** */ public void setProperty(string propertyName, int value) { setProperty(propertyName, new Value(value)); } /** */ public void setProperty(string propertyName, string value) { setProperty(propertyName, new Value(value)); } /** */ public void setProperty(string propertyName, long value) { //We use g_object_set instead of g_object_set_property, because Value doesn't like longs and ulongs for some reason. g_object_set( gObject, Str.toStringz(propertyName), value, null); } /** */ public void setProperty(string propertyName, ulong value) { g_object_set( gObject, Str.toStringz(propertyName), value, null); } deprecated("Use the member function") public static void unref(ObjectG obj) { obj.unref(); } deprecated("Use the member function") public static ObjectG doref(ObjectG obj) { return obj.doref(); } int[string] connectedSignals; void delegate(ParamSpec, ObjectG)[] onNotifyListeners; /** * The notify signal is emitted on an object when one of its * properties has been changed. Note that getting this signal * doesn't guarantee that the value of the property has actually * changed, it may also be emitted when the setter for the property * is called to reinstate the previous value. * * This signal is typically used to obtain change notification for a * single property. * * It is important to note that you must use * canonical parameter names for the property. * * Params: * dlg = The callback. * property = Set this if you only want to receive the signal for a specific property. * connectFlags = The behavior of the signal's connection. */ void addOnNotify(void delegate(ParamSpec, ObjectG) dlg, string property = "", ConnectFlags connectFlags=cast(ConnectFlags)0) { string signalName; if ( property == "" ) signalName = "notify"; else signalName = "notify::"~ property; if ( !(signalName in connectedSignals) ) { Signals.connectData( this, signalName, cast(GCallback)&callBackNotify, cast(void*)this, null, connectFlags); connectedSignals[signalName] = 1; } onNotifyListeners ~= dlg; } extern(C) static void callBackNotify(GObject* gobjectStruct, GParamSpec* pspec, ObjectG _objectG) { foreach ( void delegate(ParamSpec, ObjectG) dlg ; _objectG.onNotifyListeners ) { dlg(ObjectG.getDObject!(ParamSpec)(pspec), _objectG); } } code: end struct: ObjectClass merge: InitiallyUnownedClass struct: ParamSpecBoolean noCode: true struct: ParamSpecBoxed noCode: true struct: ParamSpecChar noCode: true struct: ParamSpecDouble noCode: true struct: ParamSpecEnum noCode: true struct: ParamSpecFlags noCode: true struct: ParamSpecFloat noCode: true struct: ParamSpecGType noCode: true struct: ParamSpecInt noCode: true struct: ParamSpecInt64 noCode: true struct: ParamSpecLong noCode: true struct: ParamSpecObject noCode: true struct: ParamSpecOverride noCode: true struct: ParamSpecParam noCode: true struct: ParamSpecPointer noCode: true struct: ParamSpecString noCode: true struct: ParamSpecUChar noCode: true struct: ParamSpecUInt noCode: true struct: ParamSpecUInt64 noCode: true struct: ParamSpecULong noCode: true struct: ParamSpecUnichar noCode: true struct: ParamSpecValueArray noCode: true struct: ParamSpecVariant noCode: true struct: Signals code: start /** */ public static gulong connectData(void* instanc, string detailedSignal, GCallback cHandler, Object data, GClosureNotify destroyData, GConnectFlags connectFlags) { return g_signal_connect_data(instanc, Str.toStringz(detailedSignal), cHandler, cast(void*)data, destroyData, connectFlags); } code: end struct: Type import: gobject.ObjectG code: start public static T* getInstanceClass(T)(ObjectG obj) { return cast(T*) (cast(GTypeInstance*)obj.getObjectGStruct()).gClass; } /** * Get the unique name that is assigned to the Objects type. * Returns: Static type name or NULL. */ public static string name(ObjectG obj) { GType type = (cast(GTypeInstance*)obj.getObjectGStruct()).gClass.gType; return name(type); } code: end struct: class: TypePlugin extend: Object implements: TypePlugin struct: Value code: start /** */ public this() { this(new GValue); } /** */ this(string value) { this(); init(GType.STRING); setString(value); } /** */ this(int value) { this(); init(GType.INT); setInt(value); } /** */ this(float value) { this(); init(GType.FLOAT); setFloat(value); } /** */ this(double value) { this(); init(GType.DOUBLE); setDouble(value); } code: end struct: WeakRef code: start /** */ this(void* object) { g_weak_ref_init(gWeakRef, object); } code: end # # Move functions defined as global into there respective classes # move: boxed_copy Boxed copy move: boxed_free Boxed free move: boxed_type_register_static Boxed type_register_static move: pointer_type_register_static Boxed move: enum_complete_type_info Enums complete_type_info move: enum_get_value Enums get_value move: enum_get_value_by_name Enums get_value_by_name move: enum_get_value_by_nick Enums get_value_by_nick move: enum_register_static Enums register_static move: flags_complete_type_info Flags complete_type_info move: flags_get_first_value Flags get_first_value move: flags_get_value_by_name Flags get_value_by_name move: flags_get_value_by_nick Flags get_value_by_nick move: flags_register_static Flags register_static # ParamSpec Constructors? move: param_spec_boolean Value move: param_spec_boxed Value move: param_spec_char Value move: param_spec_double Value move: param_spec_enum Value move: param_spec_flags Value move: param_spec_float Value move: param_spec_gtype Value move: param_spec_int Value move: param_spec_int64 Value move: param_spec_long Value move: param_spec_object Value move: param_spec_override Value move: param_spec_param Value move: param_spec_pointer Value move: param_spec_string Value move: param_spec_uchar Value move: param_spec_uint Value move: param_spec_uint64 Value move: param_spec_ulong Value move: param_spec_unichar Value move: param_spec_value_array Value move: param_spec_variant Value move: param_type_register_static ParamSpec move: param_value_convert ParamSpec move: param_value_defaults ParamSpec move: param_value_set_default ParamSpec move: param_value_validate ParamSpec move: param_values_cmp ParamSpec move: signal_accumulator_first_wins Signals accumulator_first_wins move: signal_accumulator_true_handled Signals accumulator_true_handled move: signal_add_emission_hook Signals add_emission_hook move: signal_chain_from_overridden Signals chain_from_overridden move: signal_chain_from_overridden_handler Signals chain_from_overridden_handler move: signal_connect_closure Signals connect_closure move: signal_connect_closure_by_id Signals connect_closure_by_id move: signal_connect_data Signals connect_data move: signal_connect_object Signals connect_object move: signal_emit Signals emit move: signal_emit_by_name Signals emit_by_name move: signal_emit_valist Signals emit_valist move: signal_emitv Signals emitv move: signal_get_invocation_hint Signals get_invocation_hint move: signal_handler_block Signals handler_block move: signal_handler_disconnect Signals handler_disconnect move: signal_handler_find Signals handler_find move: signal_handler_is_connected Signals handler_is_connected move: signal_handler_unblock Signals handler_unblock move: signal_handlers_block_matched Signals handlers_block_matched move: signal_handlers_destroy Signals handlers_destroy move: signal_handlers_disconnect_matched Signals handlers_disconnect_matched move: signal_handlers_unblock_matched Signals handlers_unblock_matched move: signal_has_handler_pending Signals has_handler_pending move: signal_list_ids Signals list_ids move: signal_lookup Signals lookup move: signal_name Signals name move: signal_new Signals new move: signal_new_class_handler Signals new_class_handler move: signal_new_valist Signals new_valist move: signal_newv Signals newv move: signal_override_class_closure Signals override_class_closure move: signal_override_class_handler Signals override_class_handler move: signal_parse_name Signals parse_name move: signal_query Signals query move: signal_remove_emission_hook Signals remove_emission_ move: signal_set_va_marshaller Signals set_va_marshaller move: signal_stop_emission Signals stop_emission move: signal_stop_emission_by_name Signals stop_emission_by_name move: signal_type_cclosure_new Signals type_cclosure_new move: source_set_closure Closure move: source_set_dummy_callback Closure move: strdup_value_contents Value move: type_add_class_cache_func Type add_class_cache_func move: type_add_class_private Type add_class_private move: type_add_instance_private Type add_instance_private move: type_add_interface_check Type add_interface_check move: type_add_interface_dynamic Type add_interface_dynamic move: type_add_interface_static Type add_interface_static move: type_check_class_cast Type check_class_cast move: type_check_class_is_a Type check_class_is_a move: type_check_instance Type check_instance move: type_check_instance_cast Type check_instance_cast move: type_check_instance_is_a Type check_instance_is_a move: type_check_instance_is_fundamentally_a Type check_instance_is_fundamentally_a move: type_check_is_value_type Type check_is_value_type move: type_check_value Type check_value move: type_check_value_holds Type check_value_holds move: type_children Type children move: type_create_instance Type create_instance move: type_default_interface_peek Type default_interface_peek move: type_default_interface_ref Type default_interface_ref move: type_default_interface_unref Type default_interface_unref move: type_depth Type depth move: type_ensure Type ensure move: type_free_instance Type free_instance move: type_from_name Type from_name move: type_fundamental Type fundamental move: type_fundamental_next Type fundamental_next move: type_get_plugin Type get_plugin move: type_get_qdata Type get_qdata move: type_get_type_registration_serial Type get_type_registration_serial move: type_init Type init move: type_init_with_debug_flags Type init_with_debug_flags move: type_interfaces Type interfaces move: type_is_a Type is_a move: type_name Type name move: type_name_from_class Type name_from_class move: type_name_from_instance Type name_from_instance move: type_next_base Type next_base move: type_parent Type parent move: type_qname Type qname move: type_query Type query move: type_register_dynamic Type register_dynamic move: type_register_fundamental Type register_fundamental move: type_register_static Type register_static move: type_register_static_simple Type register_static_simple move: type_remove_class_cache_func Type remove_class_cache_func move: type_remove_interface_check Type remove_interface_check move: type_set_qdata Type set_qdata move: type_test_flags Type test_flags #move: type_value_table_peek Type value_table_peek appstream-generator-0.6.8/contrib/girwrap/APILookupGio.txt000066400000000000000000000430441320016272000236210ustar00rootroot00000000000000# # Licensed under the GNU Lesser General Public License Version 3 # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the license, or # (at your option) any later version. # # This software 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library. If not, see . ############################################# ### Definitions for wrapping Gtk+ ########### ############################################# # must start with wrap wrap: gio file: Gio-2.0.gir addAliases: start public import glib.c.types; public import gobject.c.types; addAliases: end struct: class: Action extend: GObject.Object implements: Action struct: class: ActionGroup extend: GObject.Object implements: ActionGroup struct: class: AppInfo extend: GObject.Object implements: AppInfo struct: Application code: start protected class ScopedOnCommandLineDelegateWrapper { static ScopedOnCommandLineDelegateWrapper[] listeners; int delegate(Scoped!ApplicationCommandLine, Application) dlg; gulong handlerId; this(int delegate(Scoped!ApplicationCommandLine, Application) dlg) { this.dlg = dlg; this.listeners ~= this; } void remove(ScopedOnCommandLineDelegateWrapper source) { foreach(index, wrapper; listeners) { if (wrapper.handlerId == source.handlerId) { listeners[index] = null; listeners = std.algorithm.remove(listeners, index); break; } } } } /** * The ::command-line signal is emitted on the primary instance when * a commandline is not handled locally. See g_application_run() and * the #GApplicationCommandLine documentation for more information. * * Params: * commandLine = a #GApplicationCommandLine representing the * passed commandline * * Return: An integer that is set as the exit status for the calling * process. See g_application_command_line_set_exit_status(). */ gulong addOnCommandLine(int delegate(Scoped!ApplicationCommandLine, Application) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) { auto wrapper = new ScopedOnCommandLineDelegateWrapper(dlg); wrapper.handlerId = Signals.connectData( this, "command-line", cast(GCallback)&callBackScopedCommandLine, cast(void*)wrapper, cast(GClosureNotify)&callBackScopedCommandLineDestroy, connectFlags); return wrapper.handlerId; } extern(C) static int callBackScopedCommandLine(GApplication* applicationStruct, GApplicationCommandLine* commandLine, ScopedOnCommandLineDelegateWrapper wrapper) { return wrapper.dlg(scoped!ApplicationCommandLine(commandLine), wrapper.outer); } extern(C) static void callBackScopedCommandLineDestroy(ScopedOnCommandLineDelegateWrapper wrapper, GClosure* closure) { wrapper.remove(wrapper); } code: end struct: BufferedInputStream noCode: peek_buffer code: start /** * Returns the buffer with the currently available bytes. The returned * buffer must not be modified and will become invalid when reading from * the stream or filling the buffer. * * Params: * count = a #gsize to get the number of bytes available in the buffer * * Return: read-only buffer */ public ubyte[] peekBuffer() { size_t count; auto p = g_buffered_input_stream_peek_buffer(gBufferedInputStream, &count); return (cast(ubyte*)p)[0 .. count]; } code: end struct: class: Converter extend: GObject.Object implements: Converter struct: DataInputStream noCode: read_byte struct: DBusActionGroup import: glib.ConstructionException code: start /** * See_Also: get(). */ this(DBusConnection connection, string busName, string objectPath) { auto p = g_dbus_action_group_get((connection is null) ? null : connection.getDBusConnectionStruct(), Str.toStringz(busName), Str.toStringz(objectPath)); if(p is null) { throw new ConstructionException("null returned by g_dbus_action_group_get"); } this(cast(GDBusActionGroup*) p, true); } code: end struct: DBusAnnotationInfo import: glib.Str noCode: lookup code: start /** * Looks up the value of an annotation. * * The cost of this function is O(n) in number of annotations. * * Params: * annotations = A %NULL-terminated array of annotations or %NULL. * name = The name of the annotation to look up. * * Return: The value or %NULL if not found. Do not free, it is owned by @annotations. * * Since: 2.26 */ public static string lookup(DBusAnnotationInfo[] annotations, string name) { GDBusAnnotationInfo*[] annotationsArray = new GDBusAnnotationInfo*[annotations.length+1]; for ( int i = 0; i < annotations.length ; i++ ) { annotationsArray[i] = annotations[i].getDBusAnnotationInfoStruct(); } annotationsArray[$-1] = null; return Str.toString(g_dbus_annotation_info_lookup(annotationsArray.ptr, Str.toStringz(name))); } code: end struct: DBusConnection alias: new newConnection noCode: new_finish noCode: new_for_address_finish code: start /** * Finishes an operation started with g_dbus_connection_new(). * * Params: * res = A GAsyncResult obtained from the GAsyncReadyCallback * passed to g_dbus_connection_new(). * address = If true finish an address. * * Throws: GException on failure. * Throws: ConstructionException GTK+ fails to create the object. * * Since: 2.26 */ public this (AsyncResultIF res, bool address = false) { GError* err = null; GDBusConnection* p; if ( address ) { p = g_dbus_connection_new_for_address_finish((res is null) ? null : res.getAsyncResultStruct(), &err); } else { p = g_dbus_connection_new_finish((res is null) ? null : res.getAsyncResultStruct(), &err); } if (err !is null) { throw new GException( new ErrorG(err) ); } if(p is null) { throw new ConstructionException("null returned by g_dbus_connection_new_finish((res is null) ? null : res.getAsyncResultStruct(), &err)"); } this(p, true); } code: end struct: DBusMenuModel import: glib.ConstructionException code: start /** * See_Also: get(). */ this(DBusConnection connection, string busName, string objectPath) { auto p = g_dbus_menu_model_get((connection is null) ? null : connection.getDBusConnectionStruct(), Str.toStringz(busName), Str.toStringz(objectPath)); if(p is null) { throw new ConstructionException("null returned by g_dbus_menu_model_get"); } this(cast(GDBusMenuModel*) p, true); } code: end struct: class: DBusObject extend: GObject.Object implements: DBusObject struct: DBusObjectManagerClient alias: new newObjectManagerClient noCode: new_finish noCode: new_for_bus_finish code: start /** * Finishes an operation started with g_dbus_object_manager_client_new(). * * Params: * res = A GAsyncResult obtained from the GAsyncReadyCallback passed to the DBusObjectManager constructor. * forBus = If true finish an address. * * Throws: GException on failure. * Throws: ConstructionException GTK+ fails to create the object. * * Since: 2.30 */ public this (AsyncResultIF res, bool forBus = false) { GError* err = null; GDBusObjectManager* p; if ( forBus ) { p = g_dbus_object_manager_client_new_for_bus_finish((res is null) ? null : res.getAsyncResultStruct(), &err); } else { p = g_dbus_object_manager_client_new_finish((res is null) ? null : res.getAsyncResultStruct(), &err); } if (err !is null) { throw new GException( new ErrorG(err) ); } if(p is null) { throw new ConstructionException("null returned by g_dbus_object_manager_client_new_finish((res is null) ? null : res.getAsyncResultStruct(), &err)"); } this(cast(GDBusObjectManagerClient*) p, true); } code: end struct: class: DBusInterface extend: GObject.Object implements: DBusInterface struct: DBusProxy alias: new newProxy noCode: new_finish noCode: new_for_bus_finish code: start /** * Finishes creating a GDBusProxy. * * Params: * res = A GAsyncResult obtained from the GAsyncReadyCallback * function passed to g_dbus_proxy_new(). * forBus = If true finish an address. * * Throws: GException on failure. * Throws: ConstructionException GTK+ fails to create the object. * * Since: 2.26 */ public this (AsyncResultIF res, bool forBus = false) { GError* err = null; GDBusProxy* p; if ( forBus ) { p = g_dbus_proxy_new_for_bus_finish((res is null) ? null : res.getAsyncResultStruct(), &err); } else { p = g_dbus_proxy_new_finish((res is null) ? null : res.getAsyncResultStruct(), &err); } if (err !is null) { throw new GException( new ErrorG(err) ); } if(p is null) { throw new ConstructionException("null returned by g_dbus_proxy_new_finish((res is null) ? null : res.getAsyncResultStruct(), &err)"); } this(p, true); } code: end struct: DesktopAppInfo noCode: new_from_filename code: start /** * Creates a new #GDesktopAppInfo. * * Params: * filename = the path of a desktop file, in the GLib filename encoding * * Return: a new #GDesktopAppInfo or %NULL on error. * * Throws: ConstructionException GTK+ fails to create the object. */ public static DesktopAppInfo createFromFilename(string filename) { auto p = g_desktop_app_info_new_from_filename(Str.toStringz(filename)); if(p is null) { throw new ConstructionException("null returned by g_desktop_app_info_new_from_filename"); } return new DesktopAppInfo(p, true); } code: end struct: class: Drive extend: GObject.Object implements: Drive struct: class: File extend: GObject.Object implements: File struct: class: Icon extend: GObject.Object implements: Icon struct: InetAddress noCode: new_any noCode: new_loopback code: start /** * Creates a InetAddress for the "any" address (unassigned/"don't * care") for family. * * Params: * family = the address family * loopback = If true create an InetAddress for the loopback address. * * Throws: ConstructionException GTK+ fails to create the object. * * Since: 2.22 */ public this (GSocketFamily family, bool loopback = false) { GInetAddress* p; if ( loopback ) { p = g_inet_address_new_loopback(family); } else { p = g_inet_address_new_any(family); } if(p is null) { throw new ConstructionException("null returned by g_inet_address_new_any(family)"); } this(p, true); } code: end struct: NoExternal noCode: true noExternal: true struct: IOModule move: load NoExternal move: unload NoExternal move: query NoExternal struct: IOModuleScope struct: MenuItem noCode: new_section noCode: new_submenu struct: class: Mount extend: GObject.Object implements: Mount struct: class: NetworkMonitor extend: GObject.Object implements: NetworkMonitor struct: OutputStream out: vprintf error struct: PollableUtils namespace: struct: class: Proxy extend: GObject.Object implements: Proxy struct: class: ProxyResolver extend: GObject.Object implements: ProxyResolver struct: Resource alias: _register register alias: _unregister unregister struct: SettingsSchema struct: SettingsSchemaSource struct: SimpleAsyncResult noCode: new_take_error struct: SimpleProxyResolver array: new ignore_hosts array: set_ignore_hosts ignore_hosts struct: Socket ref: receive buffer ref: receive_from buffer out: receive_message messages out: receive_message num_messages struct: class: SocketConnectable extend: GObject.Object implements: SocketConnectable struct: SubprocessLauncher array: set_environ env struct: ThemedIcon noCode: new struct: class: TlsBackend extend: GObject.Object implements: TlsBackend struct: TlsPassword out: get_value length array: get_value Return length array: set_value value length array: set_value_full value length struct: UnixSocketAddress noCode: new_abstract struct: class: Volume extend: GObject.Object implements: Volume struct: VolumeMonitor import: glib.ConstructionException noCode: get code: start /** * Gets the volume monitor used by gio. * * Return: a reference to the #GVolumeMonitor used by gio. Call * g_object_unref() when done with it. */ public this() { auto p = g_volume_monitor_get(); if(p is null) { throw new ConstructionException("g_volume_monitor_get()"); } this(cast(GVolumeMonitor*) p, true); } code: end struct: move: bus_get DBusConnection get move: bus_get_finish DBusConnection get_finish move: bus_get_sync DBusConnection get_sync move: bus_own_name DBusNames own_name move: bus_own_name_on_connection DBusNames own_name_on_connection move: bus_own_name_on_connection_with_closures DBusNames own_name_on_connection_with_closures move: bus_own_name_with_closures DBusNames own_name_with_closures move: bus_unown_name DBusNames unown_name move: bus_unwatch_name DBusNames unwatch_name move: bus_watch_name DBusNames watch_name move: bus_watch_name_on_connection DBusNames watch_name_on_connection move: bus_watch_name_on_connection_with_closures DBusNames watch_name_on_connection_with_closures move: bus_watch_name_with_closures DBusNames watch_name_with_closures move: content_type_can_be_executable ContentType can_be_executable move: content_type_equals ContentType equals move: content_type_from_mime_type ContentType from_mime_type move: content_type_get_description ContentType get_description move: content_type_get_generic_icon_name ContentType get_generic_icon_name move: content_type_get_icon ContentType get_icon move: content_type_get_mime_type ContentType get_mime_type move: content_type_get_symbolic_icon ContentType get_symbolic_icon move: content_type_guess ContentType type_guess move: content_type_guess_for_tree ContentType guess_for_tree move: content_type_is_a ContentType is_a move: content_type_is_unknown ContentType is_unknown move: content_types_get_registered ContentType move: dbus_error_encode_gerror DBusError encode_gerror move: dbus_error_get_remote_error DBusError get_remote_error move: dbus_error_is_remote_error DBusError is_remote_error move: dbus_error_new_for_dbus_error DBusError new_for_dbus_error move: dbus_error_quark DBusError quark move: dbus_error_register_error DBusError register_error move: dbus_error_register_error_domain DBusError register_error_domain move: dbus_error_strip_remote_error DBusError strip_remote_error move: dbus_error_unregister_error DBusError unregister_error move: dbus_address_escape_value DBusUtilities address_escape_value move: dbus_address_get_for_bus_sync DBusUtilities address_get_for_bus_sync move: dbus_address_get_stream DBusUtilities address_get_stream move: dbus_address_get_stream_finish DBusUtilities address_get_stream_finish move: dbus_address_get_stream_sync DBusUtilities address_get_stream_sync move: dbus_generate_guid DBusUtilities generate_guid move: dbus_gvalue_to_gvariant DBusUtilities gvalue_to_gvariant move: dbus_gvariant_to_gvalue DBusUtilities gvariant_to_gvalue move: dbus_is_address DBusUtilities is_address move: dbus_is_guid DBusUtilities is_guid move: dbus_is_interface_name DBusUtilities is_interface_name move: dbus_is_member_name DBusUtilities is_member_name move: dbus_is_name DBusUtilities is_name move: dbus_is_supported_address DBusUtilities is_supported_address move: dbus_is_unique_name DBusUtilities is_unique_name struct: DBusUtilities out: address_get_stream_finish out_guid out: address_get_stream_sync out_guid move: io_error_from_errno ErrorGIO move: io_error_quark ErrorGIO move: io_modules_load_all_in_directory IOModule load_all_in_directory move: io_modules_load_all_in_directory_with_scope IOModule load_all_in_directory_with_scope move: io_modules_scan_all_in_directory IOModule scan_all_in_directory move: io_modules_scan_all_in_directory_with_scope IOModule scan_all_in_directory_with_scope move: io_scheduler_cancel_all_jobs IOSchedulerJob cancel_all_jobs move: io_scheduler_push_job IOSchedulerJob push_job move: pollable_source_new PollableUtils move: pollable_source_new_full PollableUtils move: pollable_stream_read PollableUtils move: pollable_stream_write PollableUtils move: pollable_stream_write_all PollableUtils move: resources_enumerate_children Resource move: resources_get_info Resource move: resources_lookup_data Resource move: resources_open_stream Resource move: resources_register Resource _register move: resources_unregister Resource _unregister move: simple_async_report_error_in_idle SimpleAsyncResult move: simple_async_report_gerror_in_idle SimpleAsyncResult move: simple_async_report_take_gerror_in_idle SimpleAsyncResult move: unix_is_mount_path_system_internal UnixMountEntry is_mount_path_system_internal move: unix_mount_at UnixMountEntry at move: unix_mount_compare UnixMountEntry compare move: unix_mount_free UnixMountEntry free move: unix_mount_get_device_path UnixMountEntry get_device_path move: unix_mount_get_fs_type UnixMountEntry get_fs_type move: unix_mount_get_mount_path UnixMountEntry get_mount_path move: unix_mount_guess_can_eject UnixMountEntry guess_can_eject move: unix_mount_guess_icon UnixMountEntry guess_icon move: unix_mount_guess_name UnixMountEntry guess_name move: unix_mount_guess_should_display UnixMountEntry guess_should_display move: unix_mount_guess_symbolic_icon UnixMountEntry guess_symbolic_icon move: unix_mount_is_readonly UnixMountEntry is_readonly move: unix_mount_is_system_internal UnixMountEntry is_system_internal move: unix_mount_points_changed_since UnixMountEntry points_changed_since move: unix_mount_points_get UnixMountEntry mount_points_get move: unix_mounts_changed_since UnixMountEntry mounts_changed_since move: unix_mounts_get UnixMountEntry mounts_get appstream-generator-0.6.8/contrib/girwrap/find-d-intf-files.py000077500000000000000000000010401320016272000243600ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys import glob meson_build_root = os.environ.get('MESON_BUILD_ROOT') meson_source_root = os.environ.get('MESON_SOURCE_ROOT') if not meson_build_root or not meson_source_root: print('This script should only be run by the Meson build system.') sys.exit(1) files = glob.glob(os.path.join(meson_build_root, 'girepo', '**', '*.d'), recursive=True) for fname in sorted(files): # newer versions of Meson (>= 0.43) don't like absolute paths print(os.path.relpath(fname, meson_source_root)) appstream-generator-0.6.8/contrib/setup/000077500000000000000000000000001320016272000202765ustar00rootroot00000000000000appstream-generator-0.6.8/contrib/setup/.bowerrc000066400000000000000000000001401320016272000217350ustar00rootroot00000000000000{ "directory": "js_tmp/", "analytics": false, "timeout": 120000, "interactive": false } appstream-generator-0.6.8/contrib/setup/.gitignore000066400000000000000000000000101320016272000222550ustar00rootroot00000000000000js_tmp/ appstream-generator-0.6.8/contrib/setup/build_js.sh000077500000000000000000000011211320016272000224230ustar00rootroot00000000000000#!/bin/sh set -e if [ -n "$MESON_SOURCE_ROOT" ]; then cd "$MESON_SOURCE_ROOT/contrib/setup/" fi bower --allow-root install jquery jquery-flot highlightjs JS_TARGET=../../data/templates/default/static/js [ ! -d "$JS_TARGET" ] && mkdir $JS_TARGET [ ! -d "$JS_TARGET/jquery" ] && mkdir $JS_TARGET/jquery install js_tmp/jquery/dist/*.min.js -t $JS_TARGET/jquery [ ! -d "$JS_TARGET/flot" ] && mkdir $JS_TARGET/flot install js_tmp/Flot/jquery.flot*.js -t $JS_TARGET/flot [ ! -d "$JS_TARGET/highlight" ] && mkdir $JS_TARGET/highlight install js_tmp/highlightjs/*.js -t $JS_TARGET/highlight appstream-generator-0.6.8/contrib/setup/meson-install-templates.sh000077500000000000000000000004101320016272000254110ustar00rootroot00000000000000#!/bin/sh set -e cd "$MESON_SOURCE_ROOT" echo "Installing templates..." install -d "${DESTDIR}/${MESON_INSTALL_PREFIX}/share/appstream/templates" cp -dpru --no-preserve=ownership data/templates/* -t "${DESTDIR}/${MESON_INSTALL_PREFIX}/share/appstream/templates" appstream-generator-0.6.8/contrib/subprojects/000077500000000000000000000000001320016272000215015ustar00rootroot00000000000000appstream-generator-0.6.8/contrib/subprojects/.gitignore000066400000000000000000000000261320016272000234670ustar00rootroot00000000000000* !*.wrap !.gitignore appstream-generator-0.6.8/contrib/subprojects/mustache-d.wrap000066400000000000000000000003671320016272000244340ustar00rootroot00000000000000[wrap-file] directory = mustache-d-0.1.3 source_url = https://github.com/repeatedly/mustache-d/archive/v0.1.3.tar.gz source_filename = mustache-d_v0.1.3.tar.gz.tar.gz source_hash = b8cf5fe193b11dece663ad2d7f8acbcc02ef48334f0fdc922a2dde3f8ac64b57 appstream-generator-0.6.8/contrib/update-metadata.sh.example000066400000000000000000000017151320016272000241700ustar00rootroot00000000000000#!/bin/bash # # Example script for updating AppStream metadata using appstream-generator. # This script can easily be run by a cronjob. # set -e set -o pipefail set -u SUITES="sid stretch" WORKSPACE_DIR="/srv/appstream/workspace" PUBLIC_DIR="/srv/appstream/public" # only run one instance of the script LOCKFILE="$WORKSPACE_DIR/.lock" cleanup() { rm -f "$LOCKFILE" } if ! lockfile -r8 $LOCKFILE; then echo "aborting AppStream metadata extraction because $LOCKFILE has already been locked" exit 0 fi trap cleanup 0 # Start logging logdir="$WORKSPACE_DIR/logs/`date "+%Y/%m"`" mkdir -p $logdir NOW=`date "+%d_%H%M"` LOGFILE="$logdir/${NOW}.log" exec >> "$LOGFILE" 2>&1 cd $WORKSPACE_DIR # generate fresh metadata for suite in $SUITES; do appstream-generator process $suite done # Sync updated data to public directory rsync -ak --delete-after --link-dest="$PUBLIC_DIR/" "$WORKSPACE_DIR/export/" "$PUBLIC_DIR/" # finish logging exec > /dev/null 2>&1 appstream-generator-0.6.8/data/000077500000000000000000000000001320016272000164075ustar00rootroot00000000000000appstream-generator-0.6.8/data/.gitignore000066400000000000000000000001551320016272000204000ustar00rootroot00000000000000templates/default/static/js/jquery/ templates/default/static/js/flot/ templates/default/static/js/highlight/ appstream-generator-0.6.8/data/asgen-hints.json000066400000000000000000000235731320016272000215340ustar00rootroot00000000000000{ "internal-error": { "text": [ "A fatal problem appeared in the generator.", "Please report a bug: {{msg}}"], "severity": "error" }, "internal-unknown-tag": { "text": ["The generator emitted a tag '{{tag}}' which is unknown. This is a bug in the metadata generator, please", "file a bugreport."], "severity": "warning" }, "desktop-file-error": { "text": "Unable to read data from .desktop file: {{msg}}", "severity": "error" }, "desktop-file-hidden-set": { "text": ["This .desktop file has the 'Hidden' property set. This is wrong for vendor-installed .desktop files, and", "nullifies all effects this .desktop file has, which most certainly not what was intended.", "See the specification for details."], "severity": "warning" }, "metainfo-parsing-error": { "text": "Unable to parse AppStream metainfo file, the data is likely malformed.
Error: {{msg}}", "severity": "error" }, "icon-format-unsupported": { "text": "Icon file '{{icon_fname}}' uses an unsupported image file format.", "severity": "error" }, "icon-not-found": { "text": [ "The icon '{{icon_fname}}' was not found in the archive. This issue can have multiple reasons:", "
    ", "
  • The icon is not present in the archive.
  • ", "
  • The icon is in a wrong directory.
  • ", "
  • The icon is not available in a suitable size (at least 64x64px)
  • ", "
  • On Debian and Ubuntu, the icon is a symlink. The generator cannot read symlinks on these distributions - make the icon a real file.
  • ", "
", "To make the icon easier to find, place it in /usr/share/icons/hicolor/<size>/apps and ensure the Icon= value", "of the .desktop file is set correctly." ], "severity": "error" }, "gui-app-without-icon": { "text": [ "The component is a GUI application (application which has a .desktop file for the XDG menu and Type=Application),", "but we could not find a matching icon for this application." ], "severity": "error" }, "pkg-extract-error": { "text": "Could not extract file '{{fname}}' from package '{{pkg_fname}}'. Error: {{error}}", "severity": "error" }, "pkg-empty-file": { "text": ["Could not extract file '{{fname}}' from package '{{pkg_fname}}'.", "Icon data was empty. The icon might be a symbolic link pointing at a file outside of this package.", "Please do not do that and instead place the icons in their appropriate directories in /usr/share/icons/hicolor/."], "severity": "error" }, "image-write-error": { "text": ["Could write new image generated from '{{fname}}' (package '{{pkg_fname}}'): {{error}}"], "severity": "error" }, "metainfo-no-id": { "text": ["Could not determine an ID for the component in '{{fname}}'. The AppStream metainfo file likely lacks an <id/> tag.
", "The identifier tag is essential for AppStream metadata, and must not be missing."], "severity": "error" }, "metainfo-validation-hint": { "text": "Validation of the metainfo file yielded the following hint: {{msg}}", "severity": "info" }, "metainfo-validation-issue": { "text": "Validation of the metainfo file found a problem: {{msg}}", "severity": "warning" }, "ancient-metadata": { "text": ["The AppStream metadata should be updated to follow a more recent version of the specification.
", "Please consult the XML quickstart guide for more information."], "severity": "warning" }, "legacy-metainfo-directory": { "text": ["The AppStream metainfo file '{{fname}}' was found in a legacy path.
", "Please install metainfo files into /usr/share/metainfo, as the old path will not be recognized anymore in the future."], "severity": "warning" }, "metainfo-screenshot-but-no-image": { "text": ["A screenshot has been found for this component, but apparently it does not have any images defined."], "severity": "warning" }, "screenshot-download-error": { "text": ["Error while downloading screenshot from '{{url}}': {{error}}
", "This might be a temporary server issue."], "severity": "warning" }, "screenshot-save-error": { "text": "Unable to store screenshot for '{{url}}': {{error}}", "severity": "warning" }, "screenshot-no-thumbnails": { "text": ["No thumbnails have been generated for screenshot '{{url}}'.
", "This could be a sign of the original screenshot being too small."], "severity": "info" }, "no-install-candidate": { "text": "Component has no install candidate defined. A package must be associated with a package or bundle providing it.", "severity": "error" }, "metainfo-quoted-value": { "text": "The value {{value}} in '{{field}}' is quoted, which is likely unintentional.", "severity": "info" }, "metainfo-unknown-type": { "text": ["The component has an unknown type. Please make sure this component type is mentioned in the specification, and that the", "type= property of the component root-node of the metainfo file does not contain a typing error."], "severity": "error" }, "metainfo-no-name": { "text": "Component has no name specified. Ensure that the AppStream metainfo file or the .desktop file (if there is any) specify a component name.", "severity": "error" }, "metainfo-no-summary": { "text": ["Component does not contain a short summary. Ensure that the components metainfo file has a summary tag, or that its .desktop file", "has a Comment= field set.
", "More information can be found in the Desktop Entry specification", "and the MetaInfo specification."], "severity": "error" }, "metainfo-duplicate-id": { "text": ["The component-id '{{cid}}' already appeared in package '{{pkgname}}'. AppStream-IDs must be unique, please resolve which package will be", "providing this component by default.
", "This issue may happen temporarily when metadata is moved from one package to another. In that case, ignore this issue, it will vanish soon."], "severity": "error" }, "missing-desktop-file": { "text": ["Found an AppStream metainfo XML file, but the associated .desktop file is missing. This often happens when the .desktop file is renamed, but the", "<id/> tag of the AppStream metainfo file is not adapted as well, or if the metainfo file is located in a different package than the .desktop file.
", "Please fix the packaging or work with upstream to resolve this issue."], "severity": "error" }, "missing-launchable-desktop-file": { "text": ["The metainfo file references a .desktop file with ID '{{desktop_id}}' in its launchable tag, but the file", "was not found in the same package. In order to be able to launch the software once it was installed, please place the", "metainfo file and its .desktop files in the same package."], "severity": "warning" }, "description-from-package": { "text": ["This component gets its description from the package it is located in.
", "This has several disadvantages, like poor markup, too technical descriptions for users of software centers, different components having the same description, etc.
", "Please consider writing a metainfo file for this component to take the long description upstream. In future, components without metainfo file might be dropped from the metadata entirely.", "You can consult the XML quickstart guides for more information on how to write a metainfo file."], "severity": "info" }, "metadata-serialization-failed": { "text": ["Could not create the final metadata. This could have many causes, including a generator bug, but the likeliest cause is an error in the input metadata.
", "The error message was: {{msg}}"], "severity": "error" }, "category-name-invalid": { "text": ["The category name {{category}} is invalid. The software can not be shown in this category."], "severity": "warning" }, "no-valid-category": { "text": ["This software component is no member of any valid category."], "severity": "error" }, "metainfo-license-invalid": { "text": ["The metainfo file does not seem to be licensed under a permissive license. Valid permissive licenses include FSFAP, CC0-1.0 or MIT.", "Permissive licenses are required to allow distributors to include the metadata in mixed data collections without the risk of license violations due to mutually incompatible licenses.", "If you think this message is an error and '{{license}}' is actually valid, please file a bug against AppStream."], "severity": "error" }, "font-metainfo-but-no-font": { "text": ["A metainfo file with component-type font was found, but we could not find any matching font file (TrueType or OpenType) in the package.
", "This can mean that the <provides> - <font> tags contain wrong values that we could not map to the actual fonts, or that the package simply contained no fonts at all."], "severity": "error" }, "font-load-error": { "text": "Unable to load font '{{fname}}' from package '{{pkg_fname}}: {{error}}", "severity": "error" } } appstream-generator-0.6.8/data/asgen-logo.svg000066400000000000000000000556251320016272000212000ustar00rootroot00000000000000 image/svg+xml appstream-generator-0.6.8/data/hicolor-theme-index.theme000066400000000000000000001543231320016272000233070ustar00rootroot00000000000000[Icon Theme] Name=Hicolor Comment=Fallback icon theme Hidden=true Directories=16x16/actions,16x16@2/actions,16x16/animations,16x16@2/animations,16x16/apps,16x16@2/apps,16x16/categories,16x16@2/categories,16x16/devices,16x16@2/devices,16x16/emblems,16x16@2/emblems,16x16/emotes,16x16@2/emotes,16x16/filesystems,16x16@2/filesystems,16x16/intl,16x16@2/intl,16x16/mimetypes,16x16@2/mimetypes,16x16/places,16x16@2/places,16x16/status,16x16@2/status,16x16/stock/chart,16x16@2/stock/chart,16x16/stock/code,16x16@2/stock/code,16x16/stock/data,16x16@2/stock/data,16x16/stock/form,16x16@2/stock/form,16x16/stock/image,16x16@2/stock/image,16x16/stock/io,16x16@2/stock/io,16x16/stock/media,16x16@2/stock/media,16x16/stock/navigation,16x16@2/stock/navigation,16x16/stock/net,16x16@2/stock/net,16x16/stock/object,16x16@2/stock/object,16x16/stock/table,16x16@2/stock/table,16x16/stock/text,16x16@2/stock/text,22x22/actions,22x22@2/actions,22x22/animations,22x22@2/animations,22x22/apps,22x22@2/apps,22x22/categories,22x22@2/categories,22x22/devices,22x22@2/devices,22x22/emblems,22x22@2/emblems,22x22/emotes,22x22@2/emotes,22x22/filesystems,22x22@2/filesystems,22x22/intl,22x22@2/intl,22x22/mimetypes,22x22@2/mimetypes,22x22/places,22x22@2/places,22x22/status,22x22@2/status,22x22/stock/chart,22x22@2/stock/chart,22x22/stock/code,22x22@2/stock/code,22x22/stock/data,22x22@2/stock/data,22x22/stock/form,22x22@2/stock/form,22x22/stock/image,22x22@2/stock/image,22x22/stock/io,22x22@2/stock/io,22x22/stock/media,22x22@2/stock/media,22x22/stock/navigation,22x22@2/stock/navigation,22x22/stock/net,22x22@2/stock/net,22x22/stock/object,22x22@2/stock/object,22x22/stock/table,22x22@2/stock/table,22x22/stock/text,22x22@2/stock/text,24x24/actions,24x24@2/actions,24x24/animations,24x24@2/animations,24x24/apps,24x24@2/apps,24x24/categories,24x24@2/categories,24x24/devices,24x24@2/devices,24x24/emblems,24x24@2/emblems,24x24/emotes,24x24@2/emotes,24x24/filesystems,24x24@2/filesystems,24x24/intl,24x24@2/intl,24x24/mimetypes,24x24@2/mimetypes,24x24/places,24x24@2/places,24x24/status,24x24@2/status,24x24/stock/chart,24x24@2/stock/chart,24x24/stock/code,24x24@2/stock/code,24x24/stock/data,24x24@2/stock/data,24x24/stock/form,24x24@2/stock/form,24x24/stock/image,24x24@2/stock/image,24x24/stock/io,24x24@2/stock/io,24x24/stock/media,24x24@2/stock/media,24x24/stock/navigation,24x24@2/stock/navigation,24x24/stock/net,24x24@2/stock/net,24x24/stock/object,24x24@2/stock/object,24x24/stock/table,24x24@2/stock/table,24x24/stock/text,24x24@2/stock/text,32x32/actions,32x32@2/actions,32x32/animations,32x32@2/animations,32x32/apps,32x32@2/apps,32x32/categories,32x32@2/categories,32x32/devices,32x32@2/devices,32x32/emblems,32x32@2/emblems,32x32/emotes,32x32@2/emotes,32x32/filesystems,32x32@2/filesystems,32x32/intl,32x32@2/intl,32x32/mimetypes,32x32@2/mimetypes,32x32/places,32x32@2/places,32x32/status,32x32@2/status,32x32/stock/chart,32x32@2/stock/chart,32x32/stock/code,32x32@2/stock/code,32x32/stock/data,32x32@2/stock/data,32x32/stock/form,32x32@2/stock/form,32x32/stock/image,32x32@2/stock/image,32x32/stock/io,32x32@2/stock/io,32x32/stock/media,32x32@2/stock/media,32x32/stock/navigation,32x32@2/stock/navigation,32x32/stock/net,32x32@2/stock/net,32x32/stock/object,32x32@2/stock/object,32x32/stock/table,32x32@2/stock/table,32x32/stock/text,32x32@2/stock/text,36x36/actions,36x36@2/actions,36x36/animations,36x36@2/animations,36x36/apps,36x36@2/apps,36x36/categories,36x36@2/categories,36x36/devices,36x36@2/devices,36x36/emblems,36x36@2/emblems,36x36/emotes,36x36@2/emotes,36x36/filesystems,36x36@2/filesystems,36x36/intl,36x36@2/intl,36x36/mimetypes,36x36@2/mimetypes,36x36/places,36x36@2/places,36x36/status,36x36@2/status,36x36/stock/chart,36x36@2/stock/chart,36x36/stock/code,36x36@2/stock/code,36x36/stock/data,36x36@2/stock/data,36x36/stock/form,36x36@2/stock/form,36x36/stock/image,36x36@2/stock/image,36x36/stock/io,36x36@2/stock/io,36x36/stock/media,36x36@2/stock/media,36x36/stock/navigation,36x36@2/stock/navigation,36x36/stock/net,36x36@2/stock/net,36x36/stock/object,36x36@2/stock/object,36x36/stock/table,36x36@2/stock/table,36x36/stock/text,36x36@2/stock/text,48x48/actions,48x48@2/actions,48x48/animations,48x48@2/animations,48x48/apps,48x48@2/apps,48x48/categories,48x48@2/categories,48x48/devices,48x48@2/devices,48x48/emblems,48x48@2/emblems,48x48/emotes,48x48@2/emotes,48x48/filesystems,48x48@2/filesystems,48x48/intl,48x48@2/intl,48x48/mimetypes,48x48@2/mimetypes,48x48/places,48x48@2/places,48x48/status,48x48@2/status,48x48/stock/chart,48x48@2/stock/chart,48x48/stock/code,48x48@2/stock/code,48x48/stock/data,48x48@2/stock/data,48x48/stock/form,48x48@2/stock/form,48x48/stock/image,48x48@2/stock/image,48x48/stock/io,48x48@2/stock/io,48x48/stock/media,48x48@2/stock/media,48x48/stock/navigation,48x48@2/stock/navigation,48x48/stock/net,48x48@2/stock/net,48x48/stock/object,48x48@2/stock/object,48x48/stock/table,48x48@2/stock/table,48x48/stock/text,48x48@2/stock/text,64x64/actions,64x64@2/actions,64x64/animations,64x64@2/animations,64x64/apps,64x64@2/apps,64x64/categories,64x64@2/categories,64x64/devices,64x64@2/devices,64x64/emblems,64x64@2/emblems,64x64/emotes,64x64@2/emotes,64x64/filesystems,64x64@2/filesystems,64x64/intl,64x64@2/intl,64x64/mimetypes,64x64@2/mimetypes,64x64/places,64x64@2/places,64x64/status,64x64@2/status,64x64/stock/chart,64x64@2/stock/chart,64x64/stock/code,64x64@2/stock/code,64x64/stock/data,64x64@2/stock/data,64x64/stock/form,64x64@2/stock/form,64x64/stock/image,64x64@2/stock/image,64x64/stock/io,64x64@2/stock/io,64x64/stock/media,64x64@2/stock/media,64x64/stock/navigation,64x64@2/stock/navigation,64x64/stock/net,64x64@2/stock/net,64x64/stock/object,64x64@2/stock/object,64x64/stock/table,64x64@2/stock/table,64x64/stock/text,64x64@2/stock/text,72x72/actions,72x72@2/actions,72x72/animations,72x72@2/animations,72x72/apps,72x72@2/apps,72x72/categories,72x72@2/categories,72x72/devices,72x72@2/devices,72x72/emblems,72x72@2/emblems,72x72/emotes,72x72@2/emotes,72x72/filesystems,72x72@2/filesystems,72x72/intl,72x72@2/intl,72x72/mimetypes,72x72@2/mimetypes,72x72/places,72x72@2/places,72x72/status,72x72@2/status,72x72/stock/chart,72x72@2/stock/chart,72x72/stock/code,72x72@2/stock/code,72x72/stock/data,72x72@2/stock/data,72x72/stock/form,72x72@2/stock/form,72x72/stock/image,72x72@2/stock/image,72x72/stock/io,72x72@2/stock/io,72x72/stock/media,72x72@2/stock/media,72x72/stock/navigation,72x72@2/stock/navigation,72x72/stock/net,72x72@2/stock/net,72x72/stock/object,72x72@2/stock/object,72x72/stock/table,72x72@2/stock/table,72x72/stock/text,72x72@2/stock/text,96x96/actions,96x96@2/actions,96x96/animations,96x96@2/animations,96x96/apps,96x96@2/apps,96x96/categories,96x96@2/categories,96x96/devices,96x96@2/devices,96x96/emblems,96x96@2/emblems,96x96/emotes,96x96@2/emotes,96x96/filesystems,96x96@2/filesystems,96x96/intl,96x96@2/intl,96x96/mimetypes,96x96@2/mimetypes,96x96/places,96x96@2/places,96x96/status,96x96@2/status,96x96/stock/chart,96x96@2/stock/chart,96x96/stock/code,96x96@2/stock/code,96x96/stock/data,96x96@2/stock/data,96x96/stock/form,96x96@2/stock/form,96x96/stock/image,96x96@2/stock/image,96x96/stock/io,96x96@2/stock/io,96x96/stock/media,96x96@2/stock/media,96x96/stock/navigation,96x96@2/stock/navigation,96x96/stock/net,96x96@2/stock/net,96x96/stock/object,96x96@2/stock/object,96x96/stock/table,96x96@2/stock/table,96x96/stock/text,96x96@2/stock/text,128x128/actions,128x128@2/actions,128x128/animations,128x128@2/animations,128x128/apps,128x128@2/apps,128x128/categories,128x128@2/categories,128x128/devices,128x128@2/devices,128x128/emblems,128x128@2/emblems,128x128/emotes,128x128@2/emotes,128x128/filesystems,128x128@2/filesystems,128x128/intl,128x128@2/intl,128x128/mimetypes,128x128@2/mimetypes,128x128/places,128x128@2/places,128x128/status,128x128@2/status,128x128/stock/chart,128x128@2/stock/chart,128x128/stock/code,128x128@2/stock/code,128x128/stock/data,128x128@2/stock/data,128x128/stock/form,128x128@2/stock/form,128x128/stock/image,128x128@2/stock/image,128x128/stock/io,128x128@2/stock/io,128x128/stock/media,128x128@2/stock/media,128x128/stock/navigation,128x128@2/stock/navigation,128x128/stock/net,128x128@2/stock/net,128x128/stock/object,128x128@2/stock/object,128x128/stock/table,128x128@2/stock/table,128x128/stock/text,128x128@2/stock/text,192x192/actions,192x192@2/actions,192x192/animations,192x192@2/animations,192x192/apps,192x192@2/apps,192x192/categories,192x192@2/categories,192x192/devices,192x192@2/devices,192x192/emblems,192x192@2/emblems,192x192/emotes,192x192@2/emotes,192x192/filesystems,192x192@2/filesystems,192x192/intl,192x192@2/intl,192x192/mimetypes,192x192@2/mimetypes,192x192/places,192x192@2/places,192x192/status,192x192@2/status,192x192/stock/chart,192x192@2/stock/chart,192x192/stock/code,192x192@2/stock/code,192x192/stock/data,192x192@2/stock/data,192x192/stock/form,192x192@2/stock/form,192x192/stock/image,192x192@2/stock/image,192x192/stock/io,192x192@2/stock/io,192x192/stock/media,192x192@2/stock/media,192x192/stock/navigation,192x192@2/stock/navigation,192x192/stock/net,192x192@2/stock/net,192x192/stock/object,192x192@2/stock/object,192x192/stock/table,192x192@2/stock/table,192x192/stock/text,192x192@2/stock/text,256x256/actions,256x256@2/actions,256x256/animations,256x256@2/animations,256x256/apps,256x256@2/apps,256x256/categories,256x256@2/categories,256x256/devices,256x256@2/devices,256x256/emblems,256x256@2/emblems,256x256/emotes,256x256@2/emotes,256x256/filesystems,256x256@2/filesystems,256x256/intl,256x256@2/intl,256x256/mimetypes,256x256@2/mimetypes,256x256/places,256x256@2/places,256x256/status,256x256@2/status,256x256/stock/chart,256x256@2/stock/chart,256x256/stock/code,256x256@2/stock/code,256x256/stock/data,256x256@2/stock/data,256x256/stock/form,256x256@2/stock/form,256x256/stock/image,256x256@2/stock/image,256x256/stock/io,256x256@2/stock/io,256x256/stock/media,256x256@2/stock/media,256x256/stock/navigation,256x256@2/stock/navigation,256x256/stock/net,256x256@2/stock/net,256x256/stock/object,256x256@2/stock/object,256x256/stock/table,256x256@2/stock/table,256x256/stock/text,256x256@2/stock/text,512x512/actions,512x512@2/actions,512x512/animations,512x512@2/animations,512x512/apps,512x512@2/apps,512x512/categories,512x512@2/categories,512x512/devices,512x512@2/devices,512x512/emblems,512x512@2/emblems,512x512/emotes,512x512@2/emotes,512x512/filesystems,512x512@2/filesystems,512x512/intl,512x512@2/intl,512x512/mimetypes,512x512@2/mimetypes,512x512/places,512x512@2/places,512x512/status,512x512@2/status,512x512/stock/chart,512x512@2/stock/chart,512x512/stock/code,512x512@2/stock/code,512x512/stock/data,512x512@2/stock/data,512x512/stock/form,512x512@2/stock/form,512x512/stock/image,512x512@2/stock/image,512x512/stock/io,512x512@2/stock/io,512x512/stock/media,512x512@2/stock/media,512x512/stock/navigation,512x512@2/stock/navigation,512x512/stock/net,512x512@2/stock/net,512x512/stock/object,512x512@2/stock/object,512x512/stock/table,512x512@2/stock/table,512x512/stock/text,512x512@2/stock/text,scalable/actions,scalable/animations,scalable/apps,scalable/categories,scalable/devices,scalable/emblems,scalable/emotes,scalable/filesystems,scalable/intl,scalable/mimetypes,scalable/places,scalable/status,scalable/stock/chart,scalable/stock/code,scalable/stock/data,scalable/stock/form,scalable/stock/image,scalable/stock/io,scalable/stock/media,scalable/stock/navigation,scalable/stock/net,scalable/stock/object,scalable/stock/table,scalable/stock/text,symbolic/apps [16x16/actions] Size=16 Context=Actions Type=Threshold [16x16@2/actions] Size=16 Scale=2 Context=Actions Type=Threshold [16x16/animations] Size=16 Context=Animations Type=Threshold [16x16@2/animations] Size=16 Scale=2 Context=Animations Type=Threshold [16x16/apps] Size=16 Context=Applications Type=Threshold [16x16@2/apps] Size=16 Scale=2 Context=Applications Type=Threshold [16x16/categories] Size=16 Context=Categories Type=Threshold [16x16@2/categories] Size=16 Scale=2 Context=Categories Type=Threshold [16x16/devices] Size=16 Context=Devices Type=Threshold [16x16@2/devices] Size=16 Scale=2 Context=Devices Type=Threshold [16x16/emblems] Size=16 Context=Emblems Type=Threshold [16x16@2/emblems] Size=16 Scale=2 Context=Emblems Type=Threshold [16x16/emotes] Size=16 Context=Emotes Type=Threshold [16x16@2/emotes] Size=16 Scale=2 Context=Emotes Type=Threshold [16x16/filesystems] Size=16 Context=FileSystems Type=Threshold [16x16@2/filesystems] Size=16 Scale=2 Context=FileSystems Type=Threshold [16x16/intl] Size=16 Context=International Type=Threshold [16x16@2/intl] Size=16 Scale=2 Context=International Type=Threshold [16x16/mimetypes] Size=16 Context=MimeTypes Type=Threshold [16x16@2/mimetypes] Size=16 Scale=2 Context=MimeTypes Type=Threshold [16x16/places] Size=16 Context=Places Type=Threshold [16x16@2/places] Size=16 Scale=2 Context=Places Type=Threshold [16x16/status] Size=16 Context=Status Type=Threshold [16x16@2/status] Size=16 Scale=2 Context=Status Type=Threshold [16x16/stock/chart] Size=16 Context=Stock Type=Threshold [16x16@2/stock/chart] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/code] Size=16 Context=Stock Type=Threshold [16x16@2/stock/code] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/data] Size=16 Context=Stock Type=Threshold [16x16@2/stock/data] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/form] Size=16 Context=Stock Type=Threshold [16x16@2/stock/form] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/image] Size=16 Context=Stock Type=Threshold [16x16@2/stock/image] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/io] Size=16 Context=Stock Type=Threshold [16x16@2/stock/io] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/media] Size=16 Context=Stock Type=Threshold [16x16@2/stock/media] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/navigation] Size=16 Context=Stock Type=Threshold [16x16@2/stock/navigation] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/net] Size=16 Context=Stock Type=Threshold [16x16@2/stock/net] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/object] Size=16 Context=Stock Type=Threshold [16x16@2/stock/object] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/table] Size=16 Context=Stock Type=Threshold [16x16@2/stock/table] Size=16 Scale=2 Context=Stock Type=Threshold [16x16/stock/text] Size=16 Context=Stock Type=Threshold [16x16@2/stock/text] Size=16 Scale=2 Context=Stock Type=Threshold [22x22/actions] Size=22 Context=Actions Type=Threshold [22x22@2/actions] Size=22 Scale=2 Context=Actions Type=Threshold [22x22/animations] Size=22 Context=Animations Type=Threshold [22x22@2/animations] Size=22 Scale=2 Context=Animations Type=Threshold [22x22/apps] Size=22 Context=Applications Type=Threshold [22x22@2/apps] Size=22 Scale=2 Context=Applications Type=Threshold [22x22/categories] Size=22 Context=Categories Type=Threshold [22x22@2/categories] Size=22 Scale=2 Context=Categories Type=Threshold [22x22/devices] Size=22 Context=Devices Type=Threshold [22x22@2/devices] Size=22 Scale=2 Context=Devices Type=Threshold [22x22/emblems] Size=22 Context=Emblems Type=Threshold [22x22@2/emblems] Size=22 Scale=2 Context=Emblems Type=Threshold [22x22/emotes] Size=22 Context=Emotes Type=Threshold [22x22@2/emotes] Size=22 Scale=2 Context=Emotes Type=Threshold [22x22/filesystems] Size=22 Context=FileSystems Type=Threshold [22x22@2/filesystems] Size=22 Scale=2 Context=FileSystems Type=Threshold [22x22/intl] Size=22 Context=International Type=Threshold [22x22@2/intl] Size=22 Scale=2 Context=International Type=Threshold [22x22/mimetypes] Size=22 Context=MimeTypes Type=Threshold [22x22@2/mimetypes] Size=22 Scale=2 Context=MimeTypes Type=Threshold [22x22/places] Size=22 Context=Places Type=Threshold [22x22@2/places] Size=22 Scale=2 Context=Places Type=Threshold [22x22/status] Size=22 Context=Status Type=Threshold [22x22@2/status] Size=22 Scale=2 Context=Status Type=Threshold [22x22/stock/chart] Size=22 Context=Stock Type=Threshold [22x22@2/stock/chart] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/code] Size=22 Context=Stock Type=Threshold [22x22@2/stock/code] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/data] Size=22 Context=Stock Type=Threshold [22x22@2/stock/data] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/form] Size=22 Context=Stock Type=Threshold [22x22@2/stock/form] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/image] Size=22 Context=Stock Type=Threshold [22x22@2/stock/image] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/io] Size=22 Context=Stock Type=Threshold [22x22@2/stock/io] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/media] Size=22 Context=Stock Type=Threshold [22x22@2/stock/media] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/navigation] Size=22 Context=Stock Type=Threshold [22x22@2/stock/navigation] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/net] Size=22 Context=Stock Type=Threshold [22x22@2/stock/net] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/object] Size=22 Context=Stock Type=Threshold [22x22@2/stock/object] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/table] Size=22 Context=Stock Type=Threshold [22x22@2/stock/table] Size=22 Scale=2 Context=Stock Type=Threshold [22x22/stock/text] Size=22 Context=Stock Type=Threshold [22x22@2/stock/text] Size=22 Scale=2 Context=Stock Type=Threshold [24x24/actions] Size=24 Context=Actions Type=Threshold [24x24@2/actions] Size=24 Scale=2 Context=Actions Type=Threshold [24x24/animations] Size=24 Context=Animations Type=Threshold [24x24@2/animations] Size=24 Scale=2 Context=Animations Type=Threshold [24x24/apps] Size=24 Context=Applications Type=Threshold [24x24@2/apps] Size=24 Scale=2 Context=Applications Type=Threshold [24x24/categories] Size=24 Context=Categories Type=Threshold [24x24@2/categories] Size=24 Scale=2 Context=Categories Type=Threshold [24x24/devices] Size=24 Context=Devices Type=Threshold [24x24@2/devices] Size=24 Scale=2 Context=Devices Type=Threshold [24x24/emblems] Size=24 Context=Emblems Type=Threshold [24x24@2/emblems] Size=24 Scale=2 Context=Emblems Type=Threshold [24x24/emotes] Size=24 Context=Emotes Type=Threshold [24x24@2/emotes] Size=24 Scale=2 Context=Emotes Type=Threshold [24x24/filesystems] Size=24 Context=FileSystems Type=Threshold [24x24@2/filesystems] Size=24 Scale=2 Context=FileSystems Type=Threshold [24x24/intl] Size=24 Context=International Type=Threshold [24x24@2/intl] Size=24 Scale=2 Context=International Type=Threshold [24x24/mimetypes] Size=24 Context=MimeTypes Type=Threshold [24x24@2/mimetypes] Size=24 Scale=2 Context=MimeTypes Type=Threshold [24x24/places] Size=24 Context=Places Type=Threshold [24x24@2/places] Size=24 Scale=2 Context=Places Type=Threshold [24x24/status] Size=24 Context=Status Type=Threshold [24x24@2/status] Size=24 Scale=2 Context=Status Type=Threshold [24x24/stock/chart] Size=24 Context=Stock Type=Threshold [24x24@2/stock/chart] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/code] Size=24 Context=Stock Type=Threshold [24x24@2/stock/code] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/data] Size=24 Context=Stock Type=Threshold [24x24@2/stock/data] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/form] Size=24 Context=Stock Type=Threshold [24x24@2/stock/form] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/image] Size=24 Context=Stock Type=Threshold [24x24@2/stock/image] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/io] Size=24 Context=Stock Type=Threshold [24x24@2/stock/io] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/media] Size=24 Context=Stock Type=Threshold [24x24@2/stock/media] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/navigation] Size=24 Context=Stock Type=Threshold [24x24@2/stock/navigation] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/net] Size=24 Context=Stock Type=Threshold [24x24@2/stock/net] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/object] Size=24 Context=Stock Type=Threshold [24x24@2/stock/object] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/table] Size=24 Context=Stock Type=Threshold [24x24@2/stock/table] Size=24 Scale=2 Context=Stock Type=Threshold [24x24/stock/text] Size=24 Context=Stock Type=Threshold [24x24@2/stock/text] Size=24 Scale=2 Context=Stock Type=Threshold [32x32/actions] Size=32 Context=Actions Type=Threshold [32x32@2/actions] Size=32 Scale=2 Context=Actions Type=Threshold [32x32/animations] Size=32 Context=Animations Type=Threshold [32x32@2/animations] Size=32 Scale=2 Context=Animations Type=Threshold [32x32/apps] Size=32 Context=Applications Type=Threshold [32x32@2/apps] Size=32 Scale=2 Context=Applications Type=Threshold [32x32/categories] Size=32 Context=Categories Type=Threshold [32x32@2/categories] Size=32 Scale=2 Context=Categories Type=Threshold [32x32/devices] Size=32 Context=Devices Type=Threshold [32x32@2/devices] Size=32 Scale=2 Context=Devices Type=Threshold [32x32/emblems] Size=32 Context=Emblems Type=Threshold [32x32@2/emblems] Size=32 Scale=2 Context=Emblems Type=Threshold [32x32/emotes] Size=32 Context=Emotes Type=Threshold [32x32@2/emotes] Size=32 Scale=2 Context=Emotes Type=Threshold [32x32/filesystems] Size=32 Context=FileSystems Type=Threshold [32x32@2/filesystems] Size=32 Scale=2 Context=FileSystems Type=Threshold [32x32/intl] Size=32 Context=International Type=Threshold [32x32@2/intl] Size=32 Scale=2 Context=International Type=Threshold [32x32/mimetypes] Size=32 Context=MimeTypes Type=Threshold [32x32@2/mimetypes] Size=32 Scale=2 Context=MimeTypes Type=Threshold [32x32/places] Size=32 Context=Places Type=Threshold [32x32@2/places] Size=32 Scale=2 Context=Places Type=Threshold [32x32/status] Size=32 Context=Status Type=Threshold [32x32@2/status] Size=32 Scale=2 Context=Status Type=Threshold [32x32/stock/chart] Size=32 Context=Stock Type=Threshold [32x32@2/stock/chart] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/code] Size=32 Context=Stock Type=Threshold [32x32@2/stock/code] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/data] Size=32 Context=Stock Type=Threshold [32x32@2/stock/data] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/form] Size=32 Context=Stock Type=Threshold [32x32@2/stock/form] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/image] Size=32 Context=Stock Type=Threshold [32x32@2/stock/image] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/io] Size=32 Context=Stock Type=Threshold [32x32@2/stock/io] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/media] Size=32 Context=Stock Type=Threshold [32x32@2/stock/media] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/navigation] Size=32 Context=Stock Type=Threshold [32x32@2/stock/navigation] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/net] Size=32 Context=Stock Type=Threshold [32x32@2/stock/net] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/object] Size=32 Context=Stock Type=Threshold [32x32@2/stock/object] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/table] Size=32 Context=Stock Type=Threshold [32x32@2/stock/table] Size=32 Scale=2 Context=Stock Type=Threshold [32x32/stock/text] Size=32 Context=Stock Type=Threshold [32x32@2/stock/text] Size=32 Scale=2 Context=Stock Type=Threshold [36x36/actions] Size=36 Context=Actions Type=Threshold [36x36@2/actions] Size=36 Scale=2 Context=Actions Type=Threshold [36x36/animations] Size=36 Context=Animations Type=Threshold [36x36@2/animations] Size=36 Scale=2 Context=Animations Type=Threshold [36x36/apps] Size=36 Context=Applications Type=Threshold [36x36@2/apps] Size=36 Scale=2 Context=Applications Type=Threshold [36x36/categories] Size=36 Context=Categories Type=Threshold [36x36@2/categories] Size=36 Scale=2 Context=Categories Type=Threshold [36x36/devices] Size=36 Context=Devices Type=Threshold [36x36@2/devices] Size=36 Scale=2 Context=Devices Type=Threshold [36x36/emblems] Size=36 Context=Emblems Type=Threshold [36x36@2/emblems] Size=36 Scale=2 Context=Emblems Type=Threshold [36x36/emotes] Size=36 Context=Emotes Type=Threshold [36x36@2/emotes] Size=36 Scale=2 Context=Emotes Type=Threshold [36x36/filesystems] Size=36 Context=FileSystems Type=Threshold [36x36@2/filesystems] Size=36 Scale=2 Context=FileSystems Type=Threshold [36x36/intl] Size=36 Context=International Type=Threshold [36x36@2/intl] Size=36 Scale=2 Context=International Type=Threshold [36x36/mimetypes] Size=36 Context=MimeTypes Type=Threshold [36x36@2/mimetypes] Size=36 Scale=2 Context=MimeTypes Type=Threshold [36x36/places] Size=36 Context=Places Type=Threshold [36x36@2/places] Size=36 Scale=2 Context=Places Type=Threshold [36x36/status] Size=36 Context=Status Type=Threshold [36x36@2/status] Size=36 Scale=2 Context=Status Type=Threshold [36x36/stock/chart] Size=36 Context=Stock Type=Threshold [36x36@2/stock/chart] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/code] Size=36 Context=Stock Type=Threshold [36x36@2/stock/code] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/data] Size=36 Context=Stock Type=Threshold [36x36@2/stock/data] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/form] Size=36 Context=Stock Type=Threshold [36x36@2/stock/form] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/image] Size=36 Context=Stock Type=Threshold [36x36@2/stock/image] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/io] Size=36 Context=Stock Type=Threshold [36x36@2/stock/io] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/media] Size=36 Context=Stock Type=Threshold [36x36@2/stock/media] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/navigation] Size=36 Context=Stock Type=Threshold [36x36@2/stock/navigation] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/net] Size=36 Context=Stock Type=Threshold [36x36@2/stock/net] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/object] Size=36 Context=Stock Type=Threshold [36x36@2/stock/object] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/table] Size=36 Context=Stock Type=Threshold [36x36@2/stock/table] Size=36 Scale=2 Context=Stock Type=Threshold [36x36/stock/text] Size=36 Context=Stock Type=Threshold [36x36@2/stock/text] Size=36 Scale=2 Context=Stock Type=Threshold [48x48/actions] Size=48 Context=Actions Type=Threshold [48x48@2/actions] Size=48 Scale=2 Context=Actions Type=Threshold [48x48/animations] Size=48 Context=Animations Type=Threshold [48x48@2/animations] Size=48 Scale=2 Context=Animations Type=Threshold [48x48/apps] Size=48 Context=Applications Type=Threshold [48x48@2/apps] Size=48 Scale=2 Context=Applications Type=Threshold [48x48/categories] Size=48 Context=Categories Type=Threshold [48x48@2/categories] Size=48 Scale=2 Context=Categories Type=Threshold [48x48/devices] Size=48 Context=Devices Type=Threshold [48x48@2/devices] Size=48 Scale=2 Context=Devices Type=Threshold [48x48/emblems] Size=48 Context=Emblems Type=Threshold [48x48@2/emblems] Size=48 Scale=2 Context=Emblems Type=Threshold [48x48/emotes] Size=48 Context=Emotes Type=Threshold [48x48@2/emotes] Size=48 Scale=2 Context=Emotes Type=Threshold [48x48/filesystems] Size=48 Context=FileSystems Type=Threshold [48x48@2/filesystems] Size=48 Scale=2 Context=FileSystems Type=Threshold [48x48/intl] Size=48 Context=International Type=Threshold [48x48@2/intl] Size=48 Scale=2 Context=International Type=Threshold [48x48/mimetypes] Size=48 Context=MimeTypes Type=Threshold [48x48@2/mimetypes] Size=48 Scale=2 Context=MimeTypes Type=Threshold [48x48/places] Size=48 Context=Places Type=Threshold [48x48@2/places] Size=48 Scale=2 Context=Places Type=Threshold [48x48/status] Size=48 Context=Status Type=Threshold [48x48@2/status] Size=48 Scale=2 Context=Status Type=Threshold [48x48/stock/chart] Size=48 Context=Stock Type=Threshold [48x48@2/stock/chart] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/code] Size=48 Context=Stock Type=Threshold [48x48@2/stock/code] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/data] Size=48 Context=Stock Type=Threshold [48x48@2/stock/data] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/form] Size=48 Context=Stock Type=Threshold [48x48@2/stock/form] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/image] Size=48 Context=Stock Type=Threshold [48x48@2/stock/image] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/io] Size=48 Context=Stock Type=Threshold [48x48@2/stock/io] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/media] Size=48 Context=Stock Type=Threshold [48x48@2/stock/media] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/navigation] Size=48 Context=Stock Type=Threshold [48x48@2/stock/navigation] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/net] Size=48 Context=Stock Type=Threshold [48x48@2/stock/net] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/object] Size=48 Context=Stock Type=Threshold [48x48@2/stock/object] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/table] Size=48 Context=Stock Type=Threshold [48x48@2/stock/table] Size=48 Scale=2 Context=Stock Type=Threshold [48x48/stock/text] Size=48 Context=Stock Type=Threshold [48x48@2/stock/text] Size=48 Scale=2 Context=Stock Type=Threshold [64x64/actions] Size=64 Context=Actions Type=Threshold [64x64@2/actions] Size=64 Scale=2 Context=Actions Type=Threshold [64x64/animations] Size=64 Context=Animations Type=Threshold [64x64@2/animations] Size=64 Scale=2 Context=Animations Type=Threshold [64x64/apps] Size=64 Context=Applications Type=Threshold [64x64@2/apps] Size=64 Scale=2 Context=Applications Type=Threshold [64x64/categories] Size=64 Context=Categories Type=Threshold [64x64@2/categories] Size=64 Scale=2 Context=Categories Type=Threshold [64x64/devices] Size=64 Context=Devices Type=Threshold [64x64@2/devices] Size=64 Scale=2 Context=Devices Type=Threshold [64x64/emblems] Size=64 Context=Emblems Type=Threshold [64x64@2/emblems] Size=64 Scale=2 Context=Emblems Type=Threshold [64x64/emotes] Size=64 Context=Emotes Type=Threshold [64x64@2/emotes] Size=64 Scale=2 Context=Emotes Type=Threshold [64x64/filesystems] Size=64 Context=FileSystems Type=Threshold [64x64@2/filesystems] Size=64 Scale=2 Context=FileSystems Type=Threshold [64x64/intl] Size=64 Context=International Type=Threshold [64x64@2/intl] Size=64 Scale=2 Context=International Type=Threshold [64x64/mimetypes] Size=64 Context=MimeTypes Type=Threshold [64x64@2/mimetypes] Size=64 Scale=2 Context=MimeTypes Type=Threshold [64x64/places] Size=64 Context=Places Type=Threshold [64x64@2/places] Size=64 Scale=2 Context=Places Type=Threshold [64x64/status] Size=64 Context=Status Type=Threshold [64x64@2/status] Size=64 Scale=2 Context=Status Type=Threshold [64x64/stock/chart] Size=64 Context=Stock Type=Threshold [64x64@2/stock/chart] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/code] Size=64 Context=Stock Type=Threshold [64x64@2/stock/code] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/data] Size=64 Context=Stock Type=Threshold [64x64@2/stock/data] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/form] Size=64 Context=Stock Type=Threshold [64x64@2/stock/form] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/image] Size=64 Context=Stock Type=Threshold [64x64@2/stock/image] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/io] Size=64 Context=Stock Type=Threshold [64x64@2/stock/io] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/media] Size=64 Context=Stock Type=Threshold [64x64@2/stock/media] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/navigation] Size=64 Context=Stock Type=Threshold [64x64@2/stock/navigation] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/net] Size=64 Context=Stock Type=Threshold [64x64@2/stock/net] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/object] Size=64 Context=Stock Type=Threshold [64x64@2/stock/object] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/table] Size=64 Context=Stock Type=Threshold [64x64@2/stock/table] Size=64 Scale=2 Context=Stock Type=Threshold [64x64/stock/text] Size=64 Context=Stock Type=Threshold [64x64@2/stock/text] Size=64 Scale=2 Context=Stock Type=Threshold [72x72/actions] Size=72 Context=Actions Type=Threshold [72x72@2/actions] Size=72 Scale=2 Context=Actions Type=Threshold [72x72/animations] Size=72 Context=Animations Type=Threshold [72x72@2/animations] Size=72 Scale=2 Context=Animations Type=Threshold [72x72/apps] Size=72 Context=Applications Type=Threshold [72x72@2/apps] Size=72 Scale=2 Context=Applications Type=Threshold [72x72/categories] Size=72 Context=Categories Type=Threshold [72x72@2/categories] Size=72 Scale=2 Context=Categories Type=Threshold [72x72/devices] Size=72 Context=Devices Type=Threshold [72x72@2/devices] Size=72 Scale=2 Context=Devices Type=Threshold [72x72/emblems] Size=72 Context=Emblems Type=Threshold [72x72@2/emblems] Size=72 Scale=2 Context=Emblems Type=Threshold [72x72/emotes] Size=72 Context=Emotes Type=Threshold [72x72@2/emotes] Size=72 Scale=2 Context=Emotes Type=Threshold [72x72/filesystems] Size=72 Context=FileSystems Type=Threshold [72x72@2/filesystems] Size=72 Scale=2 Context=FileSystems Type=Threshold [72x72/intl] Size=72 Context=International Type=Threshold [72x72@2/intl] Size=72 Scale=2 Context=International Type=Threshold [72x72/mimetypes] Size=72 Context=MimeTypes Type=Threshold [72x72@2/mimetypes] Size=72 Scale=2 Context=MimeTypes Type=Threshold [72x72/places] Size=72 Context=Places Type=Threshold [72x72@2/places] Size=72 Scale=2 Context=Places Type=Threshold [72x72/status] Size=72 Context=Status Type=Threshold [72x72@2/status] Size=72 Scale=2 Context=Status Type=Threshold [72x72/stock/chart] Size=72 Context=Stock Type=Threshold [72x72@2/stock/chart] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/code] Size=72 Context=Stock Type=Threshold [72x72@2/stock/code] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/data] Size=72 Context=Stock Type=Threshold [72x72@2/stock/data] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/form] Size=72 Context=Stock Type=Threshold [72x72@2/stock/form] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/image] Size=72 Context=Stock Type=Threshold [72x72@2/stock/image] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/io] Size=72 Context=Stock Type=Threshold [72x72@2/stock/io] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/media] Size=72 Context=Stock Type=Threshold [72x72@2/stock/media] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/navigation] Size=72 Context=Stock Type=Threshold [72x72@2/stock/navigation] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/net] Size=72 Context=Stock Type=Threshold [72x72@2/stock/net] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/object] Size=72 Context=Stock Type=Threshold [72x72@2/stock/object] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/table] Size=72 Context=Stock Type=Threshold [72x72@2/stock/table] Size=72 Scale=2 Context=Stock Type=Threshold [72x72/stock/text] Size=72 Context=Stock Type=Threshold [72x72@2/stock/text] Size=72 Scale=2 Context=Stock Type=Threshold [96x96/actions] Size=96 Context=Actions Type=Threshold [96x96@2/actions] Size=96 Scale=2 Context=Actions Type=Threshold [96x96/animations] Size=96 Context=Animations Type=Threshold [96x96@2/animations] Size=96 Scale=2 Context=Animations Type=Threshold [96x96/apps] Size=96 Context=Applications Type=Threshold [96x96@2/apps] Size=96 Scale=2 Context=Applications Type=Threshold [96x96/categories] Size=96 Context=Categories Type=Threshold [96x96@2/categories] Size=96 Scale=2 Context=Categories Type=Threshold [96x96/devices] Size=96 Context=Devices Type=Threshold [96x96@2/devices] Size=96 Scale=2 Context=Devices Type=Threshold [96x96/emblems] Size=96 Context=Emblems Type=Threshold [96x96@2/emblems] Size=96 Scale=2 Context=Emblems Type=Threshold [96x96/emotes] Size=96 Context=Emotes Type=Threshold [96x96@2/emotes] Size=96 Scale=2 Context=Emotes Type=Threshold [96x96/filesystems] Size=96 Context=FileSystems Type=Threshold [96x96@2/filesystems] Size=96 Scale=2 Context=FileSystems Type=Threshold [96x96/intl] Size=96 Context=International Type=Threshold [96x96@2/intl] Size=96 Scale=2 Context=International Type=Threshold [96x96/mimetypes] Size=96 Context=MimeTypes Type=Threshold [96x96@2/mimetypes] Size=96 Scale=2 Context=MimeTypes Type=Threshold [96x96/places] Size=96 Context=Places Type=Threshold [96x96@2/places] Size=96 Scale=2 Context=Places Type=Threshold [96x96/status] Size=96 Context=Status Type=Threshold [96x96@2/status] Size=96 Scale=2 Context=Status Type=Threshold [96x96/stock/chart] Size=96 Context=Stock Type=Threshold [96x96@2/stock/chart] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/code] Size=96 Context=Stock Type=Threshold [96x96@2/stock/code] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/data] Size=96 Context=Stock Type=Threshold [96x96@2/stock/data] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/form] Size=96 Context=Stock Type=Threshold [96x96@2/stock/form] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/image] Size=96 Context=Stock Type=Threshold [96x96@2/stock/image] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/io] Size=96 Context=Stock Type=Threshold [96x96@2/stock/io] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/media] Size=96 Context=Stock Type=Threshold [96x96@2/stock/media] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/navigation] Size=96 Context=Stock Type=Threshold [96x96@2/stock/navigation] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/net] Size=96 Context=Stock Type=Threshold [96x96@2/stock/net] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/object] Size=96 Context=Stock Type=Threshold [96x96@2/stock/object] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/table] Size=96 Context=Stock Type=Threshold [96x96@2/stock/table] Size=96 Scale=2 Context=Stock Type=Threshold [96x96/stock/text] Size=96 Context=Stock Type=Threshold [96x96@2/stock/text] Size=96 Scale=2 Context=Stock Type=Threshold [128x128/actions] Size=128 Context=Actions Type=Threshold [128x128@2/actions] Size=128 Scale=2 Context=Actions Type=Threshold [128x128/animations] Size=128 Context=Animations Type=Threshold [128x128@2/animations] Size=128 Scale=2 Context=Animations Type=Threshold [128x128/apps] Size=128 Context=Applications Type=Threshold [128x128@2/apps] Size=128 Scale=2 Context=Applications Type=Threshold [128x128/categories] Size=128 Context=Categories Type=Threshold [128x128@2/categories] Size=128 Scale=2 Context=Categories Type=Threshold [128x128/devices] Size=128 Context=Devices Type=Threshold [128x128@2/devices] Size=128 Scale=2 Context=Devices Type=Threshold [128x128/emblems] Size=128 Context=Emblems Type=Threshold [128x128@2/emblems] Size=128 Scale=2 Context=Emblems Type=Threshold [128x128/emotes] Size=128 Context=Emotes Type=Threshold [128x128@2/emotes] Size=128 Scale=2 Context=Emotes Type=Threshold [128x128/filesystems] Size=128 Context=FileSystems Type=Threshold [128x128@2/filesystems] Size=128 Scale=2 Context=FileSystems Type=Threshold [128x128/intl] Size=128 Context=International Type=Threshold [128x128@2/intl] Size=128 Scale=2 Context=International Type=Threshold [128x128/mimetypes] Size=128 Context=MimeTypes Type=Threshold [128x128@2/mimetypes] Size=128 Scale=2 Context=MimeTypes Type=Threshold [128x128/places] Size=128 Context=Places Type=Threshold [128x128@2/places] Size=128 Scale=2 Context=Places Type=Threshold [128x128/status] Size=128 Context=Status Type=Threshold [128x128@2/status] Size=128 Scale=2 Context=Status Type=Threshold [128x128/stock/chart] Size=128 Context=Stock Type=Threshold [128x128@2/stock/chart] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/code] Size=128 Context=Stock Type=Threshold [128x128@2/stock/code] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/data] Size=128 Context=Stock Type=Threshold [128x128@2/stock/data] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/form] Size=128 Context=Stock Type=Threshold [128x128@2/stock/form] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/image] Size=128 Context=Stock Type=Threshold [128x128@2/stock/image] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/io] Size=128 Context=Stock Type=Threshold [128x128@2/stock/io] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/media] Size=128 Context=Stock Type=Threshold [128x128@2/stock/media] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/navigation] Size=128 Context=Stock Type=Threshold [128x128@2/stock/navigation] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/net] Size=128 Context=Stock Type=Threshold [128x128@2/stock/net] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/object] Size=128 Context=Stock Type=Threshold [128x128@2/stock/object] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/table] Size=128 Context=Stock Type=Threshold [128x128@2/stock/table] Size=128 Scale=2 Context=Stock Type=Threshold [128x128/stock/text] Size=128 Context=Stock Type=Threshold [128x128@2/stock/text] Size=128 Scale=2 Context=Stock Type=Threshold [192x192/actions] Size=192 Context=Actions Type=Threshold [192x192@2/actions] Size=192 Scale=2 Context=Actions Type=Threshold [192x192/animations] Size=192 Context=Animations Type=Threshold [192x192@2/animations] Size=192 Scale=2 Context=Animations Type=Threshold [192x192/apps] Size=192 Context=Applications Type=Threshold [192x192@2/apps] Size=192 Scale=2 Context=Applications Type=Threshold [192x192/categories] Size=192 Context=Categories Type=Threshold [192x192@2/categories] Size=192 Scale=2 Context=Categories Type=Threshold [192x192/devices] Size=192 Context=Devices Type=Threshold [192x192@2/devices] Size=192 Scale=2 Context=Devices Type=Threshold [192x192/emblems] Size=192 Context=Emblems Type=Threshold [192x192@2/emblems] Size=192 Scale=2 Context=Emblems Type=Threshold [192x192/emotes] Size=192 Context=Emotes Type=Threshold [192x192@2/emotes] Size=192 Scale=2 Context=Emotes Type=Threshold [192x192/filesystems] Size=192 Context=FileSystems Type=Threshold [192x192@2/filesystems] Size=192 Scale=2 Context=FileSystems Type=Threshold [192x192/intl] Size=192 Context=International Type=Threshold [192x192@2/intl] Size=192 Scale=2 Context=International Type=Threshold [192x192/mimetypes] Size=192 Context=MimeTypes Type=Threshold [192x192@2/mimetypes] Size=192 Scale=2 Context=MimeTypes Type=Threshold [192x192/places] Size=192 Context=Places Type=Threshold [192x192@2/places] Size=192 Scale=2 Context=Places Type=Threshold [192x192/status] Size=192 Context=Status Type=Threshold [192x192@2/status] Size=192 Scale=2 Context=Status Type=Threshold [192x192/stock/chart] Size=192 Context=Stock Type=Threshold [192x192@2/stock/chart] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/code] Size=192 Context=Stock Type=Threshold [192x192@2/stock/code] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/data] Size=192 Context=Stock Type=Threshold [192x192@2/stock/data] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/form] Size=192 Context=Stock Type=Threshold [192x192@2/stock/form] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/image] Size=192 Context=Stock Type=Threshold [192x192@2/stock/image] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/io] Size=192 Context=Stock Type=Threshold [192x192@2/stock/io] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/media] Size=192 Context=Stock Type=Threshold [192x192@2/stock/media] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/navigation] Size=192 Context=Stock Type=Threshold [192x192@2/stock/navigation] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/net] Size=192 Context=Stock Type=Threshold [192x192@2/stock/net] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/object] Size=192 Context=Stock Type=Threshold [192x192@2/stock/object] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/table] Size=192 Context=Stock Type=Threshold [192x192@2/stock/table] Size=192 Scale=2 Context=Stock Type=Threshold [192x192/stock/text] Size=192 Context=Stock Type=Threshold [192x192@2/stock/text] Size=192 Scale=2 Context=Stock Type=Threshold [256x256/actions] MinSize=64 Size=256 MaxSize=256 Context=Actions Type=Scalable [256x256@2/actions] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Actions Type=Scalable [256x256/animations] MinSize=64 Size=256 MaxSize=256 Context=Animations Type=Scalable [256x256@2/animations] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Animations Type=Scalable [256x256/apps] MinSize=64 Size=256 MaxSize=256 Context=Applications Type=Scalable [256x256@2/apps] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Applications Type=Scalable [256x256/categories] MinSize=64 Size=256 MaxSize=256 Context=Categories Type=Scalable [256x256@2/categories] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Categories Type=Scalable [256x256/devices] MinSize=64 Size=256 MaxSize=256 Context=Devices Type=Scalable [256x256@2/devices] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Devices Type=Scalable [256x256/emblems] MinSize=64 Size=256 MaxSize=256 Context=Emblems Type=Scalable [256x256@2/emblems] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Emblems Type=Scalable [256x256/emotes] MinSize=64 Size=256 MaxSize=256 Context=Emotes Type=Scalable [256x256@2/emotes] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Emotes Type=Scalable [256x256/filesystems] MinSize=64 Size=256 MaxSize=256 Context=FileSystems Type=Scalable [256x256@2/filesystems] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=FileSystems Type=Scalable [256x256/intl] MinSize=64 Size=256 MaxSize=256 Context=International Type=Scalable [256x256@2/intl] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=International Type=Scalable [256x256/mimetypes] MinSize=64 Size=256 MaxSize=256 Context=MimeTypes Type=Scalable [256x256@2/mimetypes] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=MimeTypes Type=Scalable [256x256/places] MinSize=64 Size=256 MaxSize=256 Context=Places Type=Scalable [256x256@2/places] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Places Type=Scalable [256x256/status] MinSize=64 Size=256 MaxSize=256 Context=Status Type=Scalable [256x256@2/status] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Status Type=Scalable [256x256/stock/chart] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/chart] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/code] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/code] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/data] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/data] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/form] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/form] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/image] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/image] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/io] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/io] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/media] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/media] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/navigation] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/navigation] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/net] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/net] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/object] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/object] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/table] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/table] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/text] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256@2/stock/text] MinSize=64 Size=256 Scale=2 MaxSize=256 Context=Stock Type=Scalable [512x512/actions] MinSize=64 Size=512 MaxSize=512 Context=Actions Type=Scalable [512x512@2/actions] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Actions Type=Scalable [512x512/animations] MinSize=64 Size=512 MaxSize=512 Context=Animations Type=Scalable [512x512@2/animations] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Animations Type=Scalable [512x512/apps] MinSize=64 Size=512 MaxSize=512 Context=Applications Type=Scalable [512x512@2/apps] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Applications Type=Scalable [512x512/categories] MinSize=64 Size=512 MaxSize=512 Context=Categories Type=Scalable [512x512@2/categories] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Categories Type=Scalable [512x512/devices] MinSize=64 Size=512 MaxSize=512 Context=Devices Type=Scalable [512x512@2/devices] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Devices Type=Scalable [512x512/emblems] MinSize=64 Size=512 MaxSize=512 Context=Emblems Type=Scalable [512x512@2/emblems] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Emblems Type=Scalable [512x512/emotes] MinSize=64 Size=512 MaxSize=512 Context=Emotes Type=Scalable [512x512@2/emotes] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Emotes Type=Scalable [512x512/filesystems] MinSize=64 Size=512 MaxSize=512 Context=FileSystems Type=Scalable [512x512@2/filesystems] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=FileSystems Type=Scalable [512x512/intl] MinSize=64 Size=512 MaxSize=512 Context=International Type=Scalable [512x512@2/intl] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=International Type=Scalable [512x512/mimetypes] MinSize=64 Size=512 MaxSize=512 Context=MimeTypes Type=Scalable [512x512@2/mimetypes] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=MimeTypes Type=Scalable [512x512/places] MinSize=64 Size=512 MaxSize=512 Context=Places Type=Scalable [512x512@2/places] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Places Type=Scalable [512x512/status] MinSize=64 Size=512 MaxSize=512 Context=Status Type=Scalable [512x512@2/status] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Status Type=Scalable [512x512/stock/chart] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/chart] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/code] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/code] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/data] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/data] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/form] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/form] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/image] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/image] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/io] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/io] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/media] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/media] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/navigation] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/navigation] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/net] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/net] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/object] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/object] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/table] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/table] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [512x512/stock/text] MinSize=64 Size=512 MaxSize=512 Context=Stock Type=Scalable [512x512@2/stock/text] MinSize=64 Size=512 Scale=2 MaxSize=512 Context=Stock Type=Scalable [scalable/actions] MinSize=1 Size=128 MaxSize=256 Context=Actions Type=Scalable [scalable/animations] MinSize=1 Size=128 MaxSize=256 Context=Animations Type=Scalable [scalable/apps] MinSize=1 Size=128 MaxSize=256 Context=Applications Type=Scalable [scalable/categories] MinSize=1 Size=128 MaxSize=256 Context=Categories Type=Scalable [scalable/devices] MinSize=1 Size=128 MaxSize=512 Context=Devices Type=Scalable [scalable/emblems] MinSize=1 Size=128 MaxSize=256 Context=Emblems Type=Scalable [scalable/emotes] MinSize=1 Size=128 MaxSize=512 Context=Emotes Type=Scalable [scalable/filesystems] MinSize=1 Size=128 MaxSize=256 Context=FileSystems Type=Scalable [scalable/intl] MinSize=1 Size=128 MaxSize=512 Context=International Type=Scalable [scalable/mimetypes] MinSize=1 Size=128 MaxSize=256 Context=MimeTypes Type=Scalable [scalable/places] MinSize=1 Size=128 MaxSize=512 Context=Places Type=Scalable [scalable/status] MinSize=1 Size=128 MaxSize=256 Context=Status Type=Scalable [scalable/stock/chart] MinSize=1 Size=128 MaxSize=512 Context=Stock Type=Scalable [scalable/stock/code] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/data] MinSize=1 Size=128 MaxSize=512 Context=Stock Type=Scalable [scalable/stock/form] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/image] MinSize=1 Size=128 MaxSize=512 Context=Stock Type=Scalable [scalable/stock/io] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/media] MinSize=1 Size=128 MaxSize=512 Context=Stock Type=Scalable [scalable/stock/navigation] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/net] MinSize=1 Size=128 MaxSize=512 Context=Stock Type=Scalable [scalable/stock/object] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/table] MinSize=1 Size=128 MaxSize=512 Context=Stock Type=Scalable [scalable/stock/text] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [symbolic/apps] MinSize=8 Size=16 MaxSize=512 Context=Applications Type=Scalable appstream-generator-0.6.8/data/org.freedesktop.appstream.generator.metainfo.xml000066400000000000000000000032141320016272000300130ustar00rootroot00000000000000 org.freedesktop.appstream.generator FSFAP LGPL-3.0+ AppStream Generator A fast AppStream metadata generator

AppStream is a cross-distribution specification to provide metadata about software components.

The appstream-generator tool generates AppStream metadata from the repositories of a software distribution. It currently supports the following repository formats / distributions: Debian, Ubuntu, Arch Linux, RPM-MD (Fedora, Mageia).

The generator will produce AppStream collection metadata files in the AppStream YAML or XML format to be shipped to users, as well as a detailed HTML report about found components and HTML and JSON reports on issues detected with the scanned metadata. It reads .desktop files as well as metainfo files, renders fonts, scales images, caches screenshots etc. to produce high-quality metadata for AppStream based software centers to consume. Usually, appstream-generator is integrated with the existing software build & delivery workflow of a distribution.

https://github.com/ximion/appstream-generator https://github.com/ximion/appstream-generator/blob/master/docs/index.md Freedesktop appstream-generator
appstream-generator-0.6.8/data/templates/000077500000000000000000000000001320016272000204055ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/debian/000077500000000000000000000000001320016272000216275ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/debian/base.html000077700000000000000000000000001320016272000270612../default/base.htmlustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/debian/main.html000066400000000000000000000061771320016272000234540ustar00rootroot00000000000000{{#partial}}{title}Start{{/partial}} {{#partial}}{ header_content } AppStream data hints for {{project_name}} {{/partial}} {{#partial}}{ content }

Welcome!

Welcome to the AppStream Generator HTML pages!

These pages exist to provide a user-friendly view on the issues discovered by the AppStream metadata generator while extracting metadata from packages in the {{project_name}} archive. They can also be used to take a look at the raw metadata, to spot possible problems with the data itself or the generation process.

Select a suite

{{#suites}}

{{suite}}

{{/suites}}
{{#oldsuites}}

{{suite}}

{{/oldsuites}}

AppStream Generator Logo

What is AppStream and DEP-11?

AppStream is a cross-distro XML format to provide metadata for software components and to assign unique identifiers to software.
In Debian, we parse all XML provided by upstream projects as well as other metadata (.desktop-files, ...), and compile a single YAML metadata file from it, which is then shipped to users via APT.

While the official AppStream specification is based on XML, Debian uses a YAML version of the format for easier use in existing scripts and for better archive integration. This format is called DEP-11, and initially had a much wider scope in enhancing archive metadata than AppStream had. Today AppStream covers that as well, and DEP-11 is only a YAML version of AppStream.

The generated metadata can for example be used by software centers like GNOME Software or KDE Discover to display a user-friendly application-centric view on the package archive.
It can also be used by other software to find missing plugins, codecs, fonts, etc. or simply by users to install software on any Linux distribution without knowing the exact package name.

More information

See AppStream @ wiki.d.o for information about AppStream integration and usage in Debian.
The offical AppStream specification can be found at freedesktop.org, a description of the DEP-11 YAML format is hosted there as well.

You can find the source-code of the AppStream Generator here.

Log files of the generator runs are stored in logs/, machine-readable issue hints can be found in hints/, valid metadata is located in data/ and all exported media is made available via media/.

{{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/debian/static/000077500000000000000000000000001320016272000231165ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/debian/static/css/000077500000000000000000000000001320016272000237065ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/debian/static/css/highlight.css000077700000000000000000000000001320016272000354072../../../default/static/css/highlight.cssustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/debian/static/css/style.css000066400000000000000000000073421320016272000255660ustar00rootroot00000000000000html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust:100%; height:100%; } body { border-sizing: border-box; font-family: Cantarell,"Helvetica Neue",Helvetica,Arial,sans-serif; font-size: 14px; line-height: 20px; color: #333333; margin: 0; height: 93%; } a { color: #337ab7; text-decoration: none; } a { background-color: transparent; } .headbar { border-radius: 4px; display: block; border: 1px solid transparent; margin-bottom: 20px; min-height: 50px; position: relative; background-color: #f8f8f8; border-color: #e7e7e7; border-width: 0 0 1px; z-index: 1000; border-radius: 0; margin-bottom: 14px; } .headbar-content { font-size: 18px; line-height: 20px; padding: 15px; float: left; } .headbar-content-right { font-size: 14px; line-height: 20px; padding: 15px; float: right; } .content { padding: 0em 1em 0em 1em; } .wrapper { width: 60%; } .wrapper hr { border-top: none; border-bottom: 1px solid #819eb7; margin-bottom: 1em; } img.fit { max-width: 99%; max-height: 99%; } hr { border-top: none; border-bottom: 1px solid #d70a53; margin-bottom: 1em; } footer { text-align: center; margin-top: 1em; } span.avoidwrap { display: inline-block; } .infobox { border-color: #eee; border-image: none; border-radius: 3px; border-style: solid; border-width: 1px 1px 1px 5px; margin: 20px 0; padding: 20px; } .infobox h2 { margin-bottom: 5px; margin-top: 0; } .infobox p:last-child { margin-bottom: 0 } .infobox-hint { border-left-color: #1b809e; } .infobox-hint h2 { color: #1b809e; } .infobox-error { border-left-color: #ce4844; } .infobox-error h2 { color: #ce4844; } .infobox-warning { border-left-color: #aa6708; } .infobox-warning h2 { color: #aa6708; } /* label styles copied from Bootstrap */ .label { border-radius: 0.25em; color: #fff; display: inline; font-size: 75%; font-weight: 700; line-height: 1; padding: 0.2em 0.6em 0.3em; text-align: center; vertical-align: baseline; white-space: nowrap; } .label-info { background-color: #5bc0de; } .label-warning { background-color: #f0ad4e; } .label-error { background-color: #d9534f; } .label-neutral { background-color: #777; } .overviewlisting a { color: #000000; text-decoration: none; } .overviewlisting li { padding: 2px 4px 2px; } code { background-color: #f9f2f4; border-radius: 4px; color: #c7254e; font-size: 90%; padding: 2px 4px; } .well{ min-height:20px; padding:19px; margin-bottom:20px; background-color:#f5f5f5; border:1px solid #e3e3e3; border-radius:4px; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05); box-shadow:inset 0 1px 1px rgba(0,0,0,.05) } .progress { background-color: #f5f5f5; border-radius: 4px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset; height: 20px; margin-bottom: 20px; overflow: hidden; } .progress-bar { background-color: #337ab7; box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.15) inset; color: #fff; float: left; font-size: 12px; height: 100%; line-height: 20px; text-align: center; transition: width 0.6s ease 0s; width: 0; } .progress-bar-blue { background-color: #5bc0de; } .progress-bar-green { background-color: #5cb85c; } .progress-bar-yellow { background-color: #f0ad4e; } .progress-bar-red { background-color: #d9534f; } .sr-only { border: 0 none; clip: rect(0px, 0px, 0px, 0px); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } appstream-generator-0.6.8/data/templates/debian/static/img000077700000000000000000000000001320016272000277272../../default/static/img/ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/debian/static/js000077700000000000000000000000001320016272000273502../../default/static/jsustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/default/000077500000000000000000000000001320016272000220315ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/default/base.html000066400000000000000000000021621320016272000236320ustar00rootroot00000000000000 {{#block}}{ head } AppStream Report for {{project_name}} - {{#block}}{ title }{{/block}} {{#block}}{ head_extra }{{/block}} {{/block}}
{{#block}}{ header_content }{{/block}}
{{#block}}{ float_right }{{/block}}
{{#block}}{ content }{{/block}}

Generated by appstream-generator (v{{generator_version}}).

{{#block}}{ page_details }{{/block}}
appstream-generator-0.6.8/data/templates/default/issues_index.html000066400000000000000000000023241320016272000254220ustar00rootroot00000000000000{{#partial}}{title}Hints summary for {{suite}}/{{section}}{{/partial}} {{#partial}}{ header_content } ⇦ | Hints summary for {{suite}}/{{section}} {{/partial}} {{#partial}}{ content }

Metadata processing hints found for {{suite}}/{{section}}

{{#summaries}}

{{maintainer}}

    {{#packages}}
  • {{pkgname}}  {{#has_info_count}} Infos: {{info_count}} {{/has_info_count}} {{#has_warning_count}} Warnings: {{warning_count}} {{/has_warning_count}} {{#has_error_count}} Errors: {{error_count}} {{/has_error_count}}
  • {{/packages}}
{{/summaries}} {{/partial}} {{#partial}}{ float_right } Last updated on: {{time}} {{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/default/issues_page.html000066400000000000000000000035401320016272000252300ustar00rootroot00000000000000{{#partial}}{title}Issues for {{package_name}} in {{suite}}/{{section}}{{/partial}} {{#partial}}{ float_right } Last updated on: {{time}} {{/partial}} {{#partial}}{ header_content } ⇦ | {{package_name}} [{{section}}] {{/partial}} {{#partial}}{ content }

Hints for {{package_name}} in {{section}}

{{#entries}}

{{component_id}} {{#architectures}} ⚙ {{arch}} {{/architectures}}

{{#has_errors}}

Errors

    {{#errors}}
  • {{error_tag}}
    {{{error_description}}}
  • {{/errors}}
{{/has_errors}} {{#has_warnings}}

Warnings

    {{#warnings}}
  • {{warning_tag}}
    {{{warning_description}}}
  • {{/warnings}}
{{/has_warnings}} {{#has_infos}}

Hints

    {{#infos}}
  • {{info_tag}}
    {{{info_description}}}
  • {{/infos}}
{{/has_infos}} {{/entries}}
{{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/default/main.html000066400000000000000000000041571320016272000236520ustar00rootroot00000000000000{{#partial}}{title}Start{{/partial}} {{#partial}}{ header_content } AppStream data hints for {{project_name}} {{/partial}} {{#partial}}{ content }

Welcome!

Welcome to the AppStream Generator HTML pages!

These pages exist to provide a user-friendly view on the issues discovered by the AppStream metadata generator while extracting metadata from packages in the {{project_name}} archive. They can also be used to take a look at the raw metadata, to spot possible problems with the data itself or the generation process.

Select a suite

{{#suites}}

{{suite}}

{{/suites}}
{{#oldsuites}}

{{suite}}

{{/oldsuites}}

AppStream Generator Logo

What is AppStream?

AppStream is a cross-distro XML format to provide metadata for software components and to assign unique identifiers to software.
In {{project_name}}, we parse all XML provided by upstream projects as well as other metadata (.desktop-files, ...), and compile a single metadata file from it, which is then shipped to users.

The generated metadata can for example be used by software centers like GNOME Software or KDE Discover to display a user-friendly application-centric view on the package archive.
It can also be used by other software to find missing plugins, codecs, fonts, etc. or simply by users to install software on any Linux distribution without knowing the exact package name.

More information

The offical AppStream specification can be found at freedesktop.org.

You can find the source-code of the AppStream Generator here.

{{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/default/metainfo_index.html000066400000000000000000000016321320016272000257120ustar00rootroot00000000000000{{#partial}}{title}Components in {{suite}}/{{section}}{{/partial}} {{#partial}}{ header_content } ⇦ | Components summary for {{suite}}/{{section}} {{/partial}} {{#partial}}{ content }

Metadata for {{suite}}/{{section}}

{{#summaries}}

{{maintainer}}

    {{#packages}}
  • {{pkgname}} 
      {{#components}}
    • {{cid}}
    • {{/components}}
  • {{/packages}}
{{/summaries}} {{/partial}} {{#partial}}{ float_right } Last updated on: {{time}} {{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/default/metainfo_page.html000066400000000000000000000022251320016272000255160ustar00rootroot00000000000000{{#partial}}{title}{{package_name}} in {{suite}}/{{section}}{{/partial}} {{#partial}}{ float_right } Last updated on: {{time}} {{/partial}} {{#partial}}{ head_extra } {{/partial}} {{#partial}}{ header_content } ⇦ | {{package_name}} [{{section}}] {{/partial}} {{#partial}}{ content }

Metadata for {{package_name}} in {{section}}

{{#cpts}}

{{component_id}} {{#architectures}} ⚙ {{arch}} {{/architectures}}

Icon
{{metadata}}
{{/cpts}}
{{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/default/section_page.html000066400000000000000000000125261320016272000253650ustar00rootroot00000000000000{{#partial}}{title}Data for {{suite}}/{{section}}{{/partial}} {{#partial}}{ head_extra } {{/partial}} {{#partial}}{ header_content } ⇦ | AppStream data for {{project_name}}/{{suite}}/{{section}} {{/partial}} {{#partial}}{ content }

Overview for {{suite}}/{{section}}

Data

Issues - Issues found while extracting the data

Metainfo - Per-package view of the generated data

Health

Issue overview

{{valid_percentage}}% Valid
{{info_percentage}}% Infos
{{warning_percentage}}% Warnings
{{error_percentage}}% Errors
  • {{metainfo_count}} valid components
  • {{error_count}} errors
  • {{warning_count}} warnings
  • {{info_count}} infos/hints
{{/partial}} {{#partial}}{ float_right } Last updated on: {{time}} {{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/default/sections_index.html000066400000000000000000000074741320016272000257510ustar00rootroot00000000000000{{#partial}}{title}Data for the {{suite}} suite{{/partial}} {{#partial}}{ header_content } ⇦ | AppStream data for {{project_name}}/{{suite}} {{/partial}} {{#partial}}{ head_extra } {{/partial}} {{#partial}}{ content }

Select an archive section

Sections

{{#sections}}

{{section}}

{{/sections}}

Health of suite "{{suite}}"

{{#sections}}
{{section}}
{{/sections}}
{{/partial}} {{#partial}}{ float_right } Last updated on: {{time}} {{/partial}} {{> base}} appstream-generator-0.6.8/data/templates/default/static/000077500000000000000000000000001320016272000233205ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/default/static/css/000077500000000000000000000000001320016272000241105ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/default/static/css/highlight.css000066400000000000000000000021741320016272000265750ustar00rootroot00000000000000/* github.com style (c) Vasily Polovnyov */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f5f5f5; } .hljs-comment, .hljs-quote { color: #998; font-style: italic; } .hljs-keyword, .hljs-selector-tag, .hljs-subst { color: #333; font-weight: bold; } .hljs-number, .hljs-literal, .hljs-variable, .hljs-template-variable, .hljs-tag .hljs-attr { color: #008080; } .hljs-string, .hljs-doctag { color: #d14; } .hljs-title, .hljs-section, .hljs-selector-id { color: #900; font-weight: bold; } .hljs-subst { font-weight: normal; } .hljs-type, .hljs-class .hljs-title { color: #458; font-weight: bold; } .hljs-tag, .hljs-name, .hljs-attribute { color: #000080; font-weight: normal; } .hljs-regexp, .hljs-link { color: #009926; } .hljs-symbol, .hljs-bullet { color: #990073; } .hljs-built_in, .hljs-builtin-name { color: #0086b3; } .hljs-meta { color: #999; font-weight: bold; } .hljs-deletion { background: #fdd; } .hljs-addition { background: #dfd; } .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: bold; } appstream-generator-0.6.8/data/templates/default/static/css/style.css000066400000000000000000000073421320016272000257700ustar00rootroot00000000000000html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust:100%; height:100%; } body { border-sizing: border-box; font-family: Cantarell,"Helvetica Neue",Helvetica,Arial,sans-serif; font-size: 14px; line-height: 20px; color: #333333; margin: 0; height: 93%; } a { color: #337ab7; text-decoration: none; } a { background-color: transparent; } .headbar { border-radius: 4px; display: block; border: 1px solid transparent; margin-bottom: 20px; min-height: 50px; position: relative; background-color: #f8f8f8; border-color: #e7e7e7; border-width: 0 0 1px; z-index: 1000; border-radius: 0; margin-bottom: 14px; } .headbar-content { font-size: 18px; line-height: 20px; padding: 15px; float: left; } .headbar-content-right { font-size: 14px; line-height: 20px; padding: 15px; float: right; } .content { padding: 0em 1em 0em 1em; } .wrapper { width: 60%; } .wrapper hr { border-top: none; border-bottom: 1px solid #819eb7; margin-bottom: 1em; } img.fit { max-width: 99%; max-height: 99%; } hr { border-top: none; border-bottom: 1px solid #0a630d; margin-bottom: 1em; } footer { text-align: center; margin-top: 1em; } span.avoidwrap { display: inline-block; } .infobox { border-color: #eee; border-image: none; border-radius: 3px; border-style: solid; border-width: 1px 1px 1px 5px; margin: 20px 0; padding: 20px; } .infobox h2 { margin-bottom: 5px; margin-top: 0; } .infobox p:last-child { margin-bottom: 0 } .infobox-hint { border-left-color: #1b809e; } .infobox-hint h2 { color: #1b809e; } .infobox-error { border-left-color: #ce4844; } .infobox-error h2 { color: #ce4844; } .infobox-warning { border-left-color: #aa6708; } .infobox-warning h2 { color: #aa6708; } /* label styles copied from Bootstrap */ .label { border-radius: 0.25em; color: #fff; display: inline; font-size: 75%; font-weight: 700; line-height: 1; padding: 0.2em 0.6em 0.3em; text-align: center; vertical-align: baseline; white-space: nowrap; } .label-info { background-color: #5bc0de; } .label-warning { background-color: #f0ad4e; } .label-error { background-color: #d9534f; } .label-neutral { background-color: #777; } .overviewlisting a { color: #000000; text-decoration: none; } .overviewlisting li { padding: 2px 4px 2px; } code { background-color: #f9f2f4; border-radius: 4px; color: #c7254e; font-size: 90%; padding: 2px 4px; } .well{ min-height:20px; padding:19px; margin-bottom:20px; background-color:#f5f5f5; border:1px solid #e3e3e3; border-radius:4px; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05); box-shadow:inset 0 1px 1px rgba(0,0,0,.05) } .progress { background-color: #f5f5f5; border-radius: 4px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset; height: 20px; margin-bottom: 20px; overflow: hidden; } .progress-bar { background-color: #337ab7; box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.15) inset; color: #fff; float: left; font-size: 12px; height: 100%; line-height: 20px; text-align: center; transition: width 0.6s ease 0s; width: 0; } .progress-bar-blue { background-color: #5bc0de; } .progress-bar-green { background-color: #5cb85c; } .progress-bar-yellow { background-color: #f0ad4e; } .progress-bar-red { background-color: #d9534f; } .sr-only { border: 0 none; clip: rect(0px, 0px, 0px, 0px); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } appstream-generator-0.6.8/data/templates/default/static/img/000077500000000000000000000000001320016272000240745ustar00rootroot00000000000000appstream-generator-0.6.8/data/templates/default/static/img/asgen.png000066400000000000000000000365031320016272000257060ustar00rootroot00000000000000PNG  IHDR sBIT|d pHYs tEXtSoftwarewww.inkscape.org<?ٔ >}ϟھww{*pc\ǹ9q2'x,ظyM~RW,ԕR~97zf"< sӝx 1uQ~'C~?oIYDIĺ u[o /8{RA-\>e{loӘO^k{J{1_!u Qyیk }O!y:O]Y}oڨ8{T==KnU"D ӭFtn?>==ܕl{{7zQb(gMԼqt@kP;L>$wmOUvh!ڱhѝhZzD!}=d%R.M4)ԘϵLS)(wy艴,j>cmzs9n=,N=~OfS(Q#iACRdD.A)`'oF}9~)c!k^P1#Qϴ Ϩ+RiY u=Nw$Z#+CR*ٵy A3\,Y^usm4<-@I]#ԜFK IS$Q37̀pr2x+"߆; /Q+~^OE3gH{ΜB[N/):Bt2/N>:pӈ1/Ԑw-ҏةSd N7F%zR,} 0Zz)&!8IOZsk60_xH{=)>qM5"jCL1rlk[WHJ.mV%6}5cGcV`MO&!CM}YWN8!ft3Hq年.fs1;=#TJM1W R4)F,>;oIJ8]W$`7H'N<,gK?:9,+RO-,~h+q>2O\ gΜyxر"nCǦp{BjՄ<:ΰ;ͯ 575ǎ} Ɂig5@Sn1S&Φ}-9tLNN.<2== @1BD/ etuOOMzP7E}7=!=:i\looނ?G F˻'gL.~hZ>sHh!$hg{_>zte;yA3=υf#{ԤBUS裩=hZrh'A^Y=S!e; m 0HMn}uBڹRx/}-sr$_%Lxdj5Tz:<5e~6[4MhZzdӃ<*AtD4{Vb١%BjH㓓MM!|zфǎ7Z \|s#?EH %!}]!(brV%Yvd ;#!}2Kgq<81gONU_g1co4BccK*E-b1D--U67vՅzzdp9xהLAʉY4"vm!U4#vs-ߵET^esPzuZ+ѣG_1q(NMAJ“QRn.*!aMy/&'P8pd7D4t"iRH*/e7 ?`7 wݨbpz[%9@t'bfY IJB[֘br0\9!۷lTvpg!H{=OPFxZ1J$sbVvB, Bn!17CL.^ ^r^Q=7}W9vhى<:K)Rz!Rsgw.⧳UJJ/. uĄALKCUPoTc>x8N 67II.G"2IIIPݻQJ~>!f,mB%hjB{29F}xLPHp_ZĮSݪ+"K|t'38rf c < D`RSQ\f&jH(?K}@$$BB'y(%%PȐ\^46.N|f ( iW%$4)qq`Rq!܄ y110|>ʂldlL!DĬ߅}{@w7\H5)1b2+G^0g^PDKBJ. &#(6k|y<=^ 8g`q nAWLXA3&SA̡w"(HVdymsNLoj"NEqYYhqbƾSK_>I[IGLA#T@„&*x'>]%jR XOTWD2h^+^.oxak\?(1[uތŮKS( Ȯ@Ðѫ ng?Ev+2 1/m\4800D[H%2ގF ' Y9K-($EB !V 6 ;5dsU>b5͍9U3o{D 1aO&:hcR2%`k7޸k|CY9]uȹ2ƵzuDq792)Ku س #ךĘGSWSA'ڈz(N̡gpr 5إB)g:e]Sw'9W䃘eݳV2`ƃ&wV64H!Qڳ$\=#-޿'矧 3gCo)#"^+l n lpoGki ρ^E)$A zj{DC@=3/7H@I[ɹ>x {SBJƂg"sfK|K^ssȒ=}S[kU{(yt5!-ҒC-Lb[ŮCxխl%]rZs#5* ?䷘mMK[ >5 qZɠu>\4R},)sȒٓkFC:E]R'zMr,&ƽJSj؝l]!e w_{kjOgE^kL?ZhFHMw\Ư q3p(ҩfIKy̙Og$ӧNļ&< #%/rnM 3 2N%!*ݰu&-ɋGzT2$ElB((Ufr5TÚ.|2˴kIrmCܶNA2=}Ộu+~B꼵!/r1a"9HDSăl\n 9LO7Xr' d8{cjK?E~GSI%A!iHIWBY<i&?\=EU 6_Ϭ Ud\'I##xAc IL$_n7x\1LM=Qūnh%%hQRM5"]]':5J+ȣ[Rc=$-ԛ(!^6` A{\ bpŔQSƊI$C}{Qd Ԃa{u 0b\D&(#N; 9{]!{Mhm3Ay* ,^֜b>˸l9`*؏otM ؘK,GkXLNk܈rrl>iWT3dUѱ W R+a7n+Kz^Y״"c)ʩ5-Id\ d!@K4SvH~pz@dwt*Tb'cj2}JR j]6I$r~GSt'蹖vx78'eKi}=}kC{.1_nMWr1>D<Vf#Yo 8hSv޹e:{!{Xh IsZM1 /!XWw3Q1xw5eZ~ I"7 d3VޑX kk)^~\9GGW1Վ8bULy>z=z}gNB>vg' O@9E TSN, bB]֣yD*!`WVVefɹ6ԎDohyNpb}#>BNx($['"k;VNL RMcbYBGlXwx#!nvKLH5)xS.VZY'($$ B(WJ00 f,x_I21E"@osD F^F[L<Ԙ!F30JL +T)_b'h,֒2eݳR!1$2} n"8kHl f|̰o*LOOo TSWd`fS=}}?xsBB 9:륷ICN2 * TǽE6 G=7}*9>"yI D9 S~5xInq14ttYg(VI$ H b6Bb\Zśn6C*&DGQx): 9 \VuJU$ݮ..sݗ}_s?>[ʰY? ygƀ DL?IgD|T4tut1ۑ`i^k(;(*!)MA%:v=*JK(@ĆdRz`5Nk&16 ܔVQJ(Ax\8{n,]5!s /`,xbјxSs)uCgei#HĬimEd76B*q=0(H^]o9!R* &5Ѡ~'I3dI~5vA/`ZsqA3[StAjSՖ}0<,Yޞ#:XH1ڏ55[܂IdPwG EN)*!ɤԐWZC=MȽ^#J ^W#lܽllٸ`}_ X@Oʠ]%nƂQ%mQxzAs=Q=0j.fjAhh@ǘJ5N*kɑ\ڙ#sb`.|/G^ه!5 B9 vjJ)ë=뵎(HuQ~cp^:UoNQOvtJ5EN$&8lsjl RHC|TV_OHk.xV63 ~M)&v]rR.y!4~b!^4BRT Ѱ?K&隸Uʅqϗ~kí3ULŜR<t9ƍʉ$uL9{{hJ3 fC(v8iACxҗ9r'BKLuqm-!%X[RAڕm,kTmAN ;sjrNFQQoaP䘔Yur-(׈vQ I\9NT\C$Ismi*d?˄xnx(@[w= ySŒ)teO1<+>ub bp!JQ%7H%f(YM*lF *b]،آ^R!Yr!󈵒pvK(ؑHdjNZ$3r˭W>Љz{dz{{q/d>z#ׅʈBQ]HZa9,f~U*9-I~mmKf8Y=ґ'}]l"hϧ,ݫqH+Jj +mcA |׸6ؾ] SM.a$b˷v לszc)=YH0CN;m!ԳʩʫDWA/ jV׀Kn7CQ}YpK[d׷!feM%K*&g2fwGx`9qdbbu9*Wzα9l7{-pGn3)-eܑcefVɢBl$SF7]JɅԒ %XXMNnKw-b#=={{z@H&f70r!If=;u!dIUnUկ2KJb 2U@7$,2(B \D zFLu*׆Z'޻#?i/_?fΒq]J/vGw/!)bo6rԄ!uV[ڜ9bqpDrq4x0LLL@b%5$]}_ EI# iS)&+LɺR$p-!RPɌGmm܊mmBL.db"w9C;JQ U FW5W'JAj]![eE9(.R mըَ%nF`n6x[@@*f$ol%5c. B^&]Ebv!z2x!S!V.WVHEMNZ$?Dgt6db*MIEEI])}mpn DR'J%f|\DM!Z.Ud#25t1(pW:1|C-468s+_b&&#QRc4!B)ꯄ:S$ cKL(W3yBH?!3O)ё݈H(3Uז N 2rWT6Crmm%w211M P:QR6CO/ #mBBD[a3]}>,T{W@M eR))n5DCl( z 5#VVqBB$)&p3o=i[e%rrfnƢ40Rى2[PRS3ЂҚ[PfKu>:L% IȎB5݈۾BEPEU'!Ϯ>kUkcH>Xo,:v~Q"[IIC droBŵȅoT{B$h縳hHP9-.vrfe=\XYC$*tohB+J+t-l*[rE5+SlOA8ҐRHa;mW-U4Իw[xWd(fȰCٽ oLDz"Bnex${Ŷ[D,bDj U";ed]`cGAAy}GjY)/pm,O*jWUF"[WzIP3Nj lOEI =Hcݪ0{CGw-%Zق\2+cT6b~/+WmC"R!beVl(@x *Z2*2,b%9"䔕şrssT(QՍ%A6(-_ :Au'G}mAzqTbbmi(% q%o+4!ǘJ9~!8sm4Ჺ ?Ewy.1DMUS!( 1|E i>%(=DBNSI[m+r-"4Ф^b"{YiCpXjVYXJ"b%5R(Șa>1g0cJ{KET#e s^? /<'@$DoǴII.vk$|6])]A6d>҆EEzTώ^ Sccb[) HS k{qPIΙ9 gf՜ VYcRu,6UҨ!D-AMʨfG jjEqb J٢6rH6~8!6ThXBkA1rHa!.eS"6*i Ou͇/C)7T QhQ Yp-b;9nM-IT\*2!"Jဋ8d3B}ȉXsA$ 9,fHN,RDR`Ԫ#ZT~ת66Y?Ӑԋ) Ł>h3&PU+VuɆjA\ c7G'!;}n[\ gnl1OچČ3ALWH2h aU۬*o>؆Yl(cr)vB9}&f CEIv@C2#f,gˍqߴmBZ 9]Kul(A.ngC;B0>y!-ܬj/WN)|x D4MI/g/K6 ~fQ^D}NDфLmݬVu^fHʉEP"\\X7Е,Q݈LSg lK^KVrò 7vr[N ^}S]R.5ȵ iYWyG6nF̨xČMf=}KZN/ƈ&'r,3E*\l=6-咥mR)1K.G dbLJBL~2ҳh7x\" :;< yЊ׽E8B+ďf g$]t[ɢE߻HwzMXZB*#Ӊ}Z Rws]N"\9YFBd2 ^FxӼe& =)`qNzMw,QlkNԐRmN r[1:H1/?KY2ՓS3oEB`_07őL/gcb[ɶtx~}N1%.kFID7 Fs-3r霋ԗnXx˦DTH%_f^0/ٶhzjth2Sd.fVL]Iv[+GΈF4)ID$K;rr^z'h+!&b` %'E4"QŶDҀd3O#g\/ɛҭx2{[frnD+= kjFrU,:M% !q,!!S/Xe̵y'nhJx'ă>< hJyL(GZoF  /V53>+6k(u< 4pVvX 5(| FK&^ux %zL7OtNh n-9Ly5q ٿ6m0= JSr߶e B a[~`0-OK_HqBN$dR 5bJgn~S:OK0(Ad[A!@[_*-cJcJ-~)$_-ə%eTaR[өs~uJP(%գLš5}9nd>PDp9LGm"29lƂq'G6˱q-b#S,U6m`1!ᎹPWw_`>pL{+]@4r_WIp)$Id\'lk||t\6+P(~r/%842/[ $:/?eU`R!k $ӽ"/PH*}噲J'[)͍)tfuXYL-w;(O+IxJVý$10y676ؠ|uO\c$*Ŏ8#]l ^6KGC2"w?p(W',M)vBi 0W謍=x#K6m/}&)YCI[il[-\*ʹheYwku7-]rL ~5? tC66-s8*%hDL&GpGtTS$zR: ,ّnm lHe7I(ZLyEhg-B5Xo1x.SM/! hOGe&ZDf9|&?%Lr <&uOE@SW$N%*{|Й,,:b2y=W2iAI7X&T |0-S#]>~ (VTAeb闠wD(P@bÀᑒrۈl 8]`I(HN]B˹4gRR64a`RhXIZY43yG[k OyI=o^9%P pBZ20O|?H zA lńtdo%::DL7 & ~!ODZ"-sU)_VG29}5Be,2ixP1"a)Q*N=a*X^ ȼA %m?rIENDB`appstream-generator-0.6.8/data/templates/default/static/img/favicon.png000066400000000000000000000101311320016272000262230ustar00rootroot00000000000000PNG  IHDR00WbKGD pHYs tIME 9}IDATh͚yUu?;!/sBhC(# ,"˶J:DYjKavYD*ZDF1U)$( C< wtRe[wsg߽Ne_>L7d+Z_f8}޵T럪,w<-~ JVu gbY(TJcT iAgr /sJW5.V8@UU^I*~zsW|RFDDUwc#Dշ; iJբE$Isc 0P(P&ʀؑx`$Nﶰ.aY't3c7v}N6mϘ/ AZGd5Ʃ2^208&u,9 "G. ,ctwujٚպ"-S Y^}w-[i&">O^g׾}l"̈"RBbDu?y\|RD14[RD>Pmuhb"2+i^AN}Fyznno:@,U^s4FU0p",@}rrOP |VM1^t݆&Sc{l*gYf /pjRpQ$= ēccIwͲyȱ 0 wՂz>g2M LgR9)l--J-'ƴ?ۊj6J6DqYdnڵZZztM4e`p,䛝eCCnhDѽs5ᑑ CCygx N? 'Hwfv "5Zz3ñW1atm;}kr ƘyS&uF'&@Ģ 7ݴxiG=c>gSbVtRuz˃O:_ c~X=~=wwxڙ9H-xu:/NLZ<^1c?=,XI\ߊ%QHL#cce۶EY}b霹7[_d~ "ABP* TIrJtm1m߾$˲llΝ$IKW,EDNJ]+'-/1ƄkX8y UU]h5SoEFc(oj:W(`DQĊ)- K{{,1oW7Q[Y#Tc9 T92k2ɡ=z(řE9p$MyѲeÐ(QyҰs|k [m\mspnCH3$!91*=o~ |.4:3@G)`8>Z!:Dex1a;En:c&O/k:޶۳cazqf;v(6= S@U}MaA`lVWi8I84x*0dڅNsh&&pcULwCHTe yޞy DV*cNLPK2~=\Fj- XUrg-W~+.U^ t51QT޳{uۆ^#A+ejC'<٧Pݺ# JbǀtZe:v71l/Mso]k3rfj;_D>%Q8Ř|ƪo^ U~)q?{{ǏikoitQWLoWc*˺4ǡj%<_?rM5.W3q\OPM 5ƛCni(Zks)1m` t+z] $i\P-LRR=zzǬ+D9͈sl^rqz˛߽_ v^N9%s&d& msR [EjLDl,ǭֽΘwa ըHF݁ϢgqFt[n`Ĭ!|}YV f766[`m;1ڜgSmwQ$D#Y(/L}9 ᛌKK}֢hS([fNDwS<Ү#MV?29*t,6yLxGƥ4}f58MOw}w}4!{1gzǜU ͲQSApQL3pDXɌnM6-!3n2pΎ:O6X%Hj ߵ CYuQ3Z7kߡbzŘ25shc-\ksߟdAr> Y]6fݪZuIvGƍltx`sSu6Yc>{mg˥&,HE20@ y\B$(`rH|`ƑK;fK'6^JXZe"Ԍ ɝмypY~pvfT[h+%鯲$zjolΚ~ПSvaX|[fc+]9L)ISmx&?Zw7ݰnol"\yC9Hƙ.M ;4l﵎ iNGyRFe# Ή5LGg . c9+/W/nm+FJ 䑩)Ui_p?ciduUӕulש)SNN>Klt#ⷹLqVSlRۙIENDB`appstream-generator-0.6.8/data/templates/default/static/img/no-image.png000066400000000000000000000017521320016272000263030ustar00rootroot00000000000000PNG  IHDR@@iqbKGD pHYs P%tIME6jǠOOϠOMJ(rx)E,-ڔ+=IxI! ^2)!Ps `9s"@"wY:JO40|(DKBFǦ^3I=UmBl|F*E^3s/o?FW: ߤ׈pE.f ]_p~U!k7U/c(#'&f5 ɱo"ޖ0 P3A20wE 0pBlS+"P G`9pM/٬60.P |EInY pV3!7ׇͰm³;tMC|@X7%9]`Җ׏'l$Qn`2M+ǣU 4sLTV(cnCi%+" Jma? |S>$WI2KOXk8(}" "$E EȩPǿ OYB-3W '@Jc1NğYCjUi,hjO]I$^A~C<Aq4ha_#G|< QOU)#r {X:a-|m+!qU8i;[-x-xl-U)b)hfY͢_)"!dƒ}IENDB`appstream-generator-0.6.8/data/templates/ubuntu000077700000000000000000000000001320016272000230122debianustar00rootroot00000000000000appstream-generator-0.6.8/docs/000077500000000000000000000000001320016272000164265ustar00rootroot00000000000000appstream-generator-0.6.8/docs/appstream-generator.1.xml000066400000000000000000000131731320016272000232740ustar00rootroot00000000000000 18 April,2016"> GNU"> GPL"> ]> appstream-cli 2016-2017 Matthias Klumpp AppStream Generator &date; appstream-generator 1 &package; Generate AppStream metadata from distribution repositories &package; Description This manual page documents briefly the &package; command. &package; generates AppStream metadata from the repositories of a software distribution. It currently supports the following repository formats / distributions: Debian, Ubuntu, Arch Linux, RPM-MD (Fedora, Mageia). The generator will produce AppStream collection metadata files in the AppStream YAML or XML format to be shipped to users, as well as a detailed HTML report about found components and HTML and JSON reports on issues detected with the scanned metadata. It reads .desktop files as well as metainfo files, renders fonts, scales images, caches screenshots etc. to produce high-quality metadata for AppStream based software centers to consume. Usually, &package; is integrated with the existing software build & delivery workflow of a distribution. The &package; tool is based on the libappstream library for metadata conversion and analysis. If you just want to embed AppStream metadata processing into another tool, using libappstream is likely a better choice. The generator tool does some heavy lifting like rendering fonts and scaling images, which might not be necessary for simple cases. To use &package;, a asgen-config.json file is required. Its format is described in detail in the asgen-config.json documentation. For more information about the AppStream project and the other components which are part of it, take a look at the AppStream pages at Freedesktop.org. Options Process new metadata for the given distribution suite. Cleanup old/expired metadata and media files from the cache and directories. Drop all valid processed metadata and hints from the selected suite. Drop all information we have about this (partial) package-id. A package-id consists of a name/version/arch triplet. For this command, the version and architecture can be omitted. Show information associated with this (full) package-id. A package-id consists of a name/version/arch triplet. Define the workspace location. If this flag is omitted, the current directory is assumed as the workspace location. Enforce the command. Show extra debugging information. Display the version number of &package;. See Also appstreamcli (1). AUTHOR This manual page was written by Matthias Klumpp matthias@tenstral.net. appstream-generator-0.6.8/docs/asgen-config.md000066400000000000000000000132751320016272000213200ustar00rootroot00000000000000# Generator Project Configuration This document describes the options and fields which can be set in an `asgen-config.json` file. ## JSON file example An example `asgen-config.json` file may look like this: ```JSON { "ProjectName": "Tanglu", "ArchiveRoot": "/srv/archive.tanglu.org/tanglu/", "MediaBaseUrl": "http://metadata.tanglu.org/appstream/media", "HtmlBaseUrl": "http://metadata.tanglu.org/appstream/", "Backend": "debian", "Features": { "validateMetainfo": true }, "Suites": { "chromodoris": { "sections": ["main", "contrib"], "architectures": ["amd64", "i386"] }, "chromodoris-updates": { "dataPriority": 10, "baseSuite": "chromodoris", "sections": ["main", "contrib"], "architectures": ["amd64", "i386"] } } } ``` ## Description of fields ### Toplevel fields Key | Comment ------------ | ------------- ProjectName | The name of your project or distribution which ships AppStream metadata. Backend | The backend that should be used to obtain the raw data. Defaults to `debian` if not set. MetadataType | The type of the resulting AppStream metadata. Can be one of `YAML` or `XML`. If omitted, the backend's default value is used. ArchiveRoot | A local URL to the mirror of your archive, containing the dists/ and pool/ directories MediaBaseUrl | The http or https URL which should be used in the generated metadata to fetch media like screenshots or icons HtmlBaseUrl | The http or https URL to the web location where the HTML hints will be published. (This setting is optional, but recommended) Oldsuites | This key exists to support migration from an alternative appstream generator. Given a list of suite names, the output HTML will link to `suitename/index.html`. Suites | Suites which should be recognized by the generator. Each suite has the components and architectures which should be searched for metadata as children. See below for more information. Features | Disable or enable selected generator features. For a detailed description see below. CAInfo | Set the CA certificate bundle file to use for SSL peer verification. If this is not set, the generator will use the system default. AllowedCustomKeys | Set which keys of the tag are allowed to be propagated to the collection metadata output. This key takes a list of custom-key strings as value. ExportDirs | Set where to export data. The dictionary requires full paths set for the "Media", "Data", "Hints" or "Html" key. In case a value is missing, the default locations are used. ### Suite fields The `Suites` field contains a dictionary of the suites which should be processed as value. These suites can contain a selection of properties: Key | Comment ------------ | ------------- sections | A list of sections the suite possesses. The "sections" are also known as archive components in the Debian world. *(required)* architectures | A list of architectures which should be processed for this suite. *(required)* baseSuite | An optional base suite name which should be used in addition to the child suite to resolve icons (only the `main` section of that suite is considered). dataPriority | An integer value representing the priority the data generated for this suite should have. Metadata with a higher priority will override existing data (think of an `-updates` suite wanting to override data shipped with the base suite). If this is not set, AppStream client tools will assume the priority being `0`. useIconTheme | Set a specific icon theme name with highest priority for this suite. This is useful if you want a different default icon theme providing icons for generic icon names (by default, the default themes of KDE and GNOME are used). immutable | If set to `true`, the state of the metadata files and exported data will be frozen, and no more changes to the data for this suite will be allowed. This only works if the `immutableSuites` feature is enabled. ### Enabling and disabling features Several features of the metadata generator can be toggled to make it work in different scenarios. The following feature values are recognized, and can be enabled or disabled in the JSON document. If no explicit value is set for a feature, the generator will pick its default value, which is sane in most cases. Name | Comment ------------ | ------------- validateMetainfo | Validate the AppStream upstream metadata. The validation is slow, but will produce better feedback and issue hints if enabled. *Default: `ON`* processDesktop | Process .desktop files which do not have a metainfo file. If disabled, all data without metainfo file will be ignored. *Default: `ON`* noDownloads | Do not attempt any downloads. This will implicitly disable any handling of screenshots and possibly other features. Using this flag is discouraged. *Default: `OFF`* createScreenshotsStore | Mirror screenshots and create thumbnails of them in `media/`. This will yield the best experience with software-centers, and also allow full control over which screenshots are displayed. Disabling this will make clients pull screenshots from 3rd-party upstream servers. *Default: `ON`* optimizePNGSize | Use `optipng` to reduce the size of PNG images. Optipng needs to be installed. *Default: `ON`* metadataTimestamps | Write timestamps into generated metadata files. *Default: `ON`* immutableSuites | Allow suites to be marked as immutable. This is useful for distributions with fixed releases, but not for rolling release distributions or continuously updated repositories. *Default: `ON`* processFonts | Include font metadata and render fonts. *Default: `ON`* processGStreamer | Synthesise `type=codec` metadata from available GStreamer packages. Requires support in the backend, currently only implemented for Debian. *Default: `ON`* appstream-generator-0.6.8/docs/index.md000066400000000000000000000002271320016272000200600ustar00rootroot00000000000000# AppStream Generator Docs For general information check out the [README file](../README.md) See [usage.md](usage.md) for general usage information. appstream-generator-0.6.8/docs/meson.build000066400000000000000000000012051320016272000205660ustar00rootroot00000000000000# Meson definition for AppStream Generator Documentation # make manual page xsltproc = find_program('xsltproc') custom_target('man-asgen', input: 'appstream-generator.1.xml', output: 'appstream-generator.1', install: true, install_dir: join_paths(get_option('mandir'), 'man1'), command: [ xsltproc, '--nonet', '--stringparam', 'man.output.quietly', '1', '--stringparam', 'funcsynopsis.style', 'ansi', '--stringparam', 'man.th.extra1.suppress', '1', '-o', '@OUTPUT@', 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl', '@INPUT@' ] ) appstream-generator-0.6.8/docs/usage.md000066400000000000000000000045651320016272000200660ustar00rootroot00000000000000# AppStream Generator Usage ## How to use ### Generating distro metadata To generate AppStream distribution metadata for your repository, create a local mirror of the repository first. Then create a new folder, and write a `asgen-config.json` configuration file for the metadata generator. Details on the file and an example can be found in [the asgen-config docs](asgen-config.md). After the config file has been written, you can generate the metadata as follows: ```Bash cd /srv/asgen/workspace # path where the asgen-config.json file is located appstream-generator process chromodoris # replace "chromodoris" with the name of the suite you want to analyze ``` The generator is assuming you have enough memory and disk space on your machine to cache stuff. Resulting metadata will be placed in `export/data/`, machine-readable issue-hints can be found in `export/hints/` and the processed screenshots and icons are located in `export/media/`. In order to drop old packages and cruft from the databases, you should run ```Bash appstream-generator cleanup ``` every once in a while. This will drop all superseded packages and data from the caches. If you do not want to `cd` into the workspace directory, you can also use the `--workspace|-w` flag to define a workspace. ### Validating metadata You can validate the resulting metadata using the AppStream client tools. Use `appstreamcli validate .xml.gz` for XML metadata, and `dep11-validate .yml.gz` for YAML. This will check the files for mistakes and compliance with the specification. Keep in mind that the generator will always generate spec-compliant metadata, but might - depending on the input - produce data which has smaller flaws (e.g. formatting issues in the long descriptions). In these cases, issue-hints will have been emitted, so the package maintainers can address the metadata issues. ## Troubleshooting ### Memory Usage The `appstream-generator` will not hesitate to use RAM, and also decide to use lots of it if enough is available. This is especially true when scanning new packages for their contents and storing the information in the LMDB database. Ideally make sure that you are running a 64bit system with at least 4GB of RAM if you want to use the generator properly. For the generator, speed matters more than RAM usage. You can use cgroups to limit the amount of memory the generator uses. ### Profiling TODO appstream-generator-0.6.8/meson.build000066400000000000000000000160321320016272000176420ustar00rootroot00000000000000project('AppStream Generator', 'd', meson_version : '>=0.40.0', subproject_dir : 'contrib/subprojects', license : 'LGPL-3.0+', version : '0.6.8' ) asgen_version = meson.project_version() source_root = meson.source_root() build_root = meson.build_root() # # Sources # asgen_sources = ['src/app.d', 'src/asgen/zarchive.d', 'src/asgen/bindings/appstream_utils.d', 'src/asgen/bindings/cairo.d', 'src/asgen/bindings/freetype.d', 'src/asgen/bindings/freetypeTypes.d', 'src/asgen/bindings/fontconfig.d', 'src/asgen/bindings/pango.d', 'src/asgen/bindings/gdkpixbuf.d', 'src/asgen/bindings/libarchive.d', 'src/asgen/bindings/lmdb.d', 'src/asgen/bindings/rsvg.d', 'src/asgen/config.d', 'src/asgen/contentsstore.d', 'src/asgen/datastore.d', 'src/asgen/engine.d', 'src/asgen/extractor.d', 'src/asgen/handlers/desktopparser.d', 'src/asgen/handlers/fonthandler.d', 'src/asgen/handlers/iconhandler.d', 'src/asgen/handlers/metainfoparser.d', 'src/asgen/handlers/metainfovalidator.d', 'src/asgen/handlers/package.d', 'src/asgen/handlers/screenshothandler.d', 'src/asgen/hint.d', 'src/asgen/font.d', 'src/asgen/image.d', 'src/asgen/logging.d', 'src/asgen/reportgenerator.d', 'src/asgen/result.d', 'src/asgen/utils.d', join_paths(build_root, 'src', 'asgen', 'defines.d'), ] backend_sources = [ 'src/asgen/backends/interfaces.d', 'src/asgen/backends/dummy/package.d', 'src/asgen/backends/dummy/dummypkg.d', 'src/asgen/backends/dummy/pkgindex.d', 'src/asgen/backends/archlinux/package.d', 'src/asgen/backends/archlinux/alpkg.d', 'src/asgen/backends/archlinux/alpkgindex.d', 'src/asgen/backends/archlinux/listfile.d', 'src/asgen/backends/debian/package.d', 'src/asgen/backends/debian/debpkg.d', 'src/asgen/backends/debian/debpkgindex.d', 'src/asgen/backends/debian/tagfile.d', 'src/asgen/backends/debian/debutils.d', 'src/asgen/backends/ubuntu/package.d', 'src/asgen/backends/ubuntu/ubupkg.d', 'src/asgen/backends/ubuntu/ubupkgindex.d', 'src/asgen/backends/rpmmd/package.d', 'src/asgen/backends/rpmmd/rpmpkg.d', 'src/asgen/backends/rpmmd/rpmpkgindex.d', ] # # Sanitizers & quirk fixes # # Set a few flags to work around compiler bugs if meson.get_compiler('d').get_id() == 'gcc' add_global_arguments(['-Wl,--push-state,-no-as-needed -lcurl -Wl,--pop-state', '-no-pie'], language : 'd') add_global_link_arguments('-no-pie', language : 'd') endif # TODO: Make this a real option, not something to manually enable. #add_global_arguments(['-sanitize=address'], language : 'd') #add_global_link_arguments('-L-l:libasan.so.4.0.0', language : 'd') # # Dependencies # src_dir = include_directories('src/') glib_dep = dependency('glib-2.0') gobject_dep = dependency('gobject-2.0') gio_dep = dependency('gio-2.0') appstream_dep = dependency('appstream', version : '>= 0.11.7') lmdb_dep = dependency('lmdb', version : '>= 0.9') mustache_dep = dependency('mustache-d', required: false) archive_dep = dependency('libarchive', version : '>= 3.2') cairo_dep = dependency('cairo', version : '>= 1.12') gdkpixbuf_dep = dependency('gdk-pixbuf-2.0') rsvg_dep = dependency('librsvg-2.0') curl_dep = dependency('libcurl') freetype_dep = dependency('freetype2') pango_dep = dependency('pango') fontconfig_dep = dependency('fontconfig') if not mustache_dep.found() mustache_sp = subproject('mustache-d') mustache_dep = declare_dependency(link_with: mustache_sp.get_variable('mustache_lib'), include_directories: mustache_sp.get_variable('src_dir') ) endif # # Build interfaces from GIR # gir_to_d_prog = find_program('girtod') gir_wrap_dir = source_root + '/contrib/girwrap/' gir_d_intf_dir = build_root + '/girepo/' message('Generating D interfaces from GIR...') girtod_gen = run_command(gir_to_d_prog.path(), '-i', gir_wrap_dir, '-o', gir_d_intf_dir) if girtod_gen.returncode() != 0 error('Unable to build D intefaces from GIR:\n' + girtod_gen.stderr() + girtod_gen.stdout()) endif gir_bind_dir = include_directories('girepo') # Enlist D GIR interface sources dgir_glob_script = run_command(source_root + '/contrib/girwrap/find-d-intf-files.py') if dgir_glob_script.returncode() != 0 error('Unable to find D GIR interface source code:\n' + dgir_glob_script.stdout() + dgir_glob_script.stderr()) endif gir_binding_sources = dgir_glob_script.stdout().strip().split('\n') # # Download JS stuff and additional sources if we couldn't find them # # Download JavaScript assets if requested if get_option('download-js') message('Downloading JavaScript libraries...') if run_command('[', '-d', 'data/templates/default/static/js', ']').returncode() != 0 getjs_cmd = run_command([source_root + '/contrib/setup/build_js.sh']) if getjs_cmd.returncode() != 0 error('Unable to download JavaScript files with Bower:\n' + getjs_cmd.stdout() + getjs_cmd.stderr()) endif endif endif # # Build and test # subdir('src/asgen') girbind_lib = static_library('girbindings', [gir_binding_sources], include_directories: [gir_bind_dir] ) asgen_exe = executable('appstream-generator', [asgen_sources, backend_sources], include_directories: [src_dir, gir_bind_dir], dependencies: [glib_dep, gobject_dep, gio_dep, appstream_dep, lmdb_dep, archive_dep, mustache_dep, cairo_dep, gdkpixbuf_dep, rsvg_dep, curl_dep, freetype_dep, fontconfig_dep, pango_dep], link_with: [girbind_lib], install: true ) asgen_test_exe = executable('asgen_test', [asgen_sources, backend_sources], include_directories: [src_dir, gir_bind_dir], dependencies: [glib_dep, gobject_dep, gio_dep, appstream_dep, lmdb_dep, archive_dep, mustache_dep, cairo_dep, gdkpixbuf_dep, rsvg_dep, curl_dep, freetype_dep, fontconfig_dep, pango_dep], link_with: [girbind_lib], d_args: meson.get_compiler('d').unittest_args() ) test('asgen_tests', asgen_test_exe) subdir('docs') # # Install # # data install_data('data/asgen-hints.json', install_dir: 'share/appstream') install_data('data/hicolor-theme-index.theme', install_dir: 'share/appstream') install_data('data/org.freedesktop.appstream.generator.metainfo.xml', install_dir: join_paths (get_option ('datadir'), 'metainfo')) # templates #install_subdir('data/templates/', install_dir: 'share/appstream') # FIXME: Doesn't handle dir symlinks correctly meson.add_install_script(source_root + '/contrib/setup/meson-install-templates.sh') appstream-generator-0.6.8/meson_options.txt000066400000000000000000000003011320016272000211250ustar00rootroot00000000000000# # Options for AppStream Generator # option('download-js', type: 'boolean', value: true, description: 'Whether we should download JavaScript with Bower automatically.' ) appstream-generator-0.6.8/src/000077500000000000000000000000001320016272000162655ustar00rootroot00000000000000appstream-generator-0.6.8/src/app.d000066400000000000000000000114021320016272000172100ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ import std.stdio; import std.path : getcwd, buildPath; import std.getopt; import std.string : format; import core.stdc.stdlib; import asgen.logging; import asgen.config; import asgen.engine; import asgen.defines : ASGEN_VERSION; private immutable helpText = "Usage: appstream-generator [OPTION...] - AppStream Generator. AppStream Metadata Generator Subcommands: process SUITE [SECTION] - Process new metadata for the given distribution suite. cleanup - Cleanup old metadata and media files. remove-found SUITE - Drop all valid processed metadata and hints. forget PKID - Drop all information we have about this (partial) package-id. info PKID - Show information associated with this (full) package-id. Help Options: -h, --help Show help options Application Options: --version Show the program version. --verbose Show extra debugging information. --force Force action. -w|--workspace Define the workspace location."; version (unittest) { void main () {} } else { void main(string[] args) { string command; bool verbose; bool showHelp; bool showVersion; bool forceAction; string wdir = getcwd (); // parse command-line options try { getopt (args, "help|h", &showHelp, "verbose", &verbose, "version", &showVersion, "force", &forceAction, "workspace|w", &wdir); } catch (Exception e) { writeln ("Unable to parse parameters: ", e.msg); exit (1); } if (showHelp) { writeln (helpText); return; } if (showVersion) { writeln ("Generator version: ", ASGEN_VERSION); return; } if (args.length < 2) { writeln ("No subcommand specified!"); return; } auto conf = Config.get (); try { conf.loadFromFile (buildPath (wdir, "asgen-config.json")); } catch (Exception e) { writefln ("Unable to load configuration: %s", e.msg); exit (4); } scope (exit) { import std.file; if (exists (conf.getTmpDir ())) rmdirRecurse (conf.getTmpDir ()); } // globally enable verbose mode, if requested if (verbose) { asgen.logging.setVerbose (true); } auto engine = new Engine (); engine.forced = forceAction; command = args[1]; switch (command) { case "run": case "process": if (args.length < 3) { writeln ("Invalid number of parameters: You need to specify at least a suite name."); exit (1); } if (args.length > 4) { writeln ("Invalid number of parameters: You need to specify a suite name and (optionally) a section name."); exit (1); } if (args.length == 3) engine.run (args[2]); else engine.run (args[2], args[3]); break; case "cleanup": engine.runCleanup (); break; case "remove-found": if (args.length != 3) { writeln ("Invalid number of parameters: You need to specify a suite name."); exit (1); } engine.removeHintsComponents (args[2]); break; case "forget": if (args.length != 3) { writeln ("Invalid number of parameters: You need to specify a package-id (partial IDs are allowed)."); exit (1); } engine.forgetPackage (args[2]); break; case "info": if (args.length != 3) { writeln ("Invalid number of parameters: You need to specify a package-id."); exit (1); } engine.printPackageInfo (args[2]); break; default: writeln (format ("The command '%s' is unknown.", command)); exit (1); break; } } } appstream-generator-0.6.8/src/asgen/000077500000000000000000000000001320016272000173625ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/backends/000077500000000000000000000000001320016272000211345ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/backends/archlinux/000077500000000000000000000000001320016272000231315ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/backends/archlinux/alpkg.d000066400000000000000000000047111320016272000243770ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.archlinux.alpkg; import std.stdio; import std.string; import std.array : empty; import asgen.logging; import asgen.zarchive; import asgen.backends.interfaces; final class ArchPackage : Package { private: string pkgname; string pkgver; string pkgarch; string pkgmaintainer; string[string] desc; string pkgFname; string[] contentsL; ArchiveDecompressor archive; public: override @property string name () const { return pkgname; } @property void name (string val) { pkgname = val; } override @property string ver () const { return pkgver; } @property void ver (string val) { pkgver = val; } override @property string arch () const { return pkgarch; } @property void arch (string val) { pkgarch = val; } override @property const(string[string]) description () const { return desc; } override @property string filename () const { return pkgFname; } @property void filename (string fname) { pkgFname = fname; } override @property string maintainer () const { return pkgmaintainer; } @property void maintainer (string maint) { pkgmaintainer = maint; } void setDescription (string text, string locale) { desc[locale] = text; } override const(ubyte)[] getFileData (string fname) { if (!archive.isOpen ()) { archive.open (this.filename); } return archive.readData (fname); } @property override string[] contents () { return contentsL; } @property void contents (string[] c) { contentsL = c; } override void close () { } } appstream-generator-0.6.8/src/asgen/backends/archlinux/alpkgindex.d000066400000000000000000000116241320016272000254300ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.archlinux.alpkgindex; import std.stdio; import std.path; import std.string; import std.algorithm : canFind; import std.array : appender; static import std.file; import asgen.logging; import asgen.zarchive; import asgen.utils : escapeXml; import asgen.backends.interfaces; import asgen.backends.archlinux.alpkg; import asgen.backends.archlinux.listfile; final class ArchPackageIndex : PackageIndex { private: string rootDir; Package[][string] pkgCache; public: this (string dir) { this.rootDir = dir; if (!std.file.exists (dir)) throw new Exception ("Directory '%s' does not exist.", dir); } void release () { pkgCache = null; } private void setPkgDescription (ArchPackage pkg, string pkgDesc) { if (pkgDesc is null) return; auto desc = "

%s

".format (pkgDesc.escapeXml); pkg.setDescription (desc, "C"); } private Package[] loadPackages (string suite, string section, string arch) { auto pkgRoot = buildPath (rootDir, suite, section, "os", arch); auto listsTarFname = buildPath (pkgRoot, format ("%s.files.tar.gz", section)); if (!std.file.exists (listsTarFname)) { logWarning ("Package lists tarball '%s' does not exist.", listsTarFname); return []; } auto ad = new ArchiveDecompressor (); ad.open (listsTarFname); logDebug ("Opened: %s", listsTarFname); ArchPackage[string] pkgsMap; foreach (entry; ad.read ()) { auto archPkid = dirName (entry.fname); ArchPackage pkg; if (archPkid in pkgsMap) { pkg = pkgsMap[archPkid]; } else { pkg = new ArchPackage (); pkgsMap[archPkid] = pkg; } auto infoBaseName = baseName (entry.fname); if (infoBaseName == "desc") { // we have the description file, add information to this package auto descF = new ListFile (); descF.loadData (entry.data); pkg.name = descF.getEntry ("NAME"); pkg.ver = descF.getEntry ("VERSION"); pkg.arch = descF.getEntry ("ARCH"); pkg.maintainer = descF.getEntry ("PACKAGER"); pkg.filename = buildPath (pkgRoot, descF.getEntry ("FILENAME")); setPkgDescription (pkg, descF.getEntry ("DESC")); } else if (infoBaseName == "files") { // we found a content index, add content information to the package auto filesF = new ListFile (); filesF.loadData (entry.data); auto filesStr = filesF.getEntry ("FILES"); if (filesStr is null) { if (!pkg.name.canFind ("-meta")) { logWarning ("Package '%s' has no file list set. Ignoring it.", pkg.toString ()); continue; } } auto contents = appender!(string[]); foreach (l; filesStr.splitLines ()) contents ~= "/" ~ l; pkg.contents = contents.data; } } // perform a sanity check, so we will never emit invalid packages auto pkgs = appender!(Package[]); foreach (ref pkg; pkgsMap.byValue ()) { if (pkg.isValid) pkgs ~= pkg; else logError ("Found an invalid package (name, architecture or version is missing). This is a bug."); } return pkgs.data; } Package[] packagesFor (string suite, string section, string arch) { if ((suite == "arch") || (suite == "archlinux")) suite = ""; immutable id = "%s-%s-%s".format (suite, section, arch); if (id !in pkgCache) { auto pkgs = loadPackages (suite, section, arch); synchronized (this) pkgCache[id] = pkgs; } return pkgCache[id]; } bool hasChanges (DataStore dstore, string suite, string section, string arch) { return true; } } appstream-generator-0.6.8/src/asgen/backends/archlinux/listfile.d000066400000000000000000000050561320016272000251170ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.archlinux.listfile; import std.stdio; import std.string; final class ListFile { private: string[string] entries; public: this () { } void loadData (const(ubyte)[] data) { string[] content; auto dataStr = cast(string) data; content = dataStr.splitLines (); string blockName = null; foreach (l; content) { if ((l.startsWith ("%")) && (l.endsWith ("%"))) { blockName = l[1..$-1]; continue; } if (l == "") { blockName = null; continue; } if (blockName !is null) { if (blockName in entries) entries[blockName] ~= "\n" ~ l; else entries[blockName] = l; continue; } } } string getEntry (string name) { auto resP = name in entries; if (resP is null) // we found nothing return null; return *resP; } } unittest { writeln ("TEST: ", "Backend::Archlinux - ListFile"); string data = "%FILENAME% a2ps-4.14-6-x86_64.pkg.tar.xz %NAME% a2ps %VERSION% 4.14-6 %DESC% An Any to PostScript filter %CSIZE% 629320 %MULTILINE% Blah1 BLUBB2 EtcEtcEtc3 %SHA256SUM% a629a0e0eca0d96a97eb3564f01be495772439df6350600c93120f5ac7f3a1b5"; auto lf = new ListFile (); lf.loadData (cast(ubyte[]) data); assert (lf.getEntry ("FILENAME") == "a2ps-4.14-6-x86_64.pkg.tar.xz"); assert (lf.getEntry ("VERSION") == "4.14-6"); assert (lf.getEntry ("MULTILINE") == "Blah1\nBLUBB2\nEtcEtcEtc3"); assert (lf.getEntry ("SHA256SUM") == "a629a0e0eca0d96a97eb3564f01be495772439df6350600c93120f5ac7f3a1b5"); } appstream-generator-0.6.8/src/asgen/backends/archlinux/package.d000066400000000000000000000002041320016272000246650ustar00rootroot00000000000000 module asgen.backends.archlinux; public import asgen.backends.archlinux.alpkg; public import asgen.backends.archlinux.alpkgindex; appstream-generator-0.6.8/src/asgen/backends/debian/000077500000000000000000000000001320016272000223565ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/backends/debian/debpkg.d000066400000000000000000000160701320016272000237630ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.debian.debpkg; import std.stdio; import std.string; import std.path; import std.array : empty, appender; import std.file : rmdirRecurse, mkdirRecurse; static import std.file; import asgen.config; import asgen.zarchive; import asgen.backends.interfaces; import asgen.logging; import asgen.utils : isRemote, downloadFile; class DebPackage : Package { private: string pkgname; string pkgver; string pkgarch; string pkgmaintainer; string[string] desc; string[string] summ; GStreamer gstreamer; bool contentsRead; string[] contentsL; string tmpDir; string dataArchive; string controlArchive; string debFname; public: final @property override string name () const { return pkgname; } final @property override string ver () const { return pkgver; } final @property override string arch () const { return pkgarch; } final @property override GStreamer gst () { return gstreamer; } final @property void gst (GStreamer gst) { gstreamer = gst; } final @property override const(string[string]) description () const { return desc; } final @property override const(string[string]) summary () const { return summ; } override final @property string filename () const { if (debFname.isRemote) { immutable path = buildNormalizedPath (tmpDir, debFname.baseName); synchronized (this) { downloadFile (debFname, path); } return path; } return debFname; } final @property void filename (string fname) { debFname = fname; } override final @property string maintainer () const { return pkgmaintainer; } final @property void maintainer (string maint) { pkgmaintainer = maint; } this (string pname, string pver, string parch) { pkgname = pname; pkgver = pver; pkgarch = parch; contentsRead = false; auto conf = Config.get (); tmpDir = buildPath (conf.getTmpDir (), format ("%s-%s_%s", name, ver, arch)); } ~this () { // FIXME: We can't properly clean up because we can't GC-allocate in a destructor (leads to crashes), // see if this is fixed in a future version of D, or simply don't use the GC in close (). // close (); } final void setDescription (string text, string locale) { desc[locale] = text; } final void setSummary (string text, string locale) { summ[locale] = text; } private auto openPayloadArchive () { auto pa = new ArchiveDecompressor (); if (!dataArchive) { import std.regex; // extract the payload to a temporary location first pa.open (this.filename); mkdirRecurse (tmpDir); string[] files; try { files = pa.extractFilesByRegex (ctRegex!(r"data\.*"), tmpDir); } catch (Exception e) { throw e; } if (files.length == 0) return null; dataArchive = files[0]; } pa.open (dataArchive); return pa; } protected final void extractPackage (const string dest = buildPath (tmpDir, name)) { import std.file : exists; import std.regex : ctRegex; if (!dest.exists) mkdirRecurse (dest); auto pa = openPayloadArchive (); pa.extractArchive (dest); } private final auto openControlArchive () { auto ca = new ArchiveDecompressor (); if (!controlArchive) { import std.regex; // extract the payload to a temporary location first ca.open (this.filename); mkdirRecurse (tmpDir); string[] files; try { files = ca.extractFilesByRegex (ctRegex!(r"control\.*"), tmpDir); } catch (Exception e) { throw e; } if (files.empty) return null; controlArchive = files[0]; } ca.open (controlArchive); return ca; } override final const(ubyte)[] getFileData (string fname) { auto pa = openPayloadArchive (); return pa.readData (fname); } @property override final string[] contents () { import std.utf; if (contentsRead) return contentsL; if (pkgname.endsWith ("icon-theme")) { // the md5sums file does not contain symbolic links - while that is okay-ish for regular // packages, it is not acceptable for icon themes, since those rely on symlinks to provide // aliases for certain icons. So, use the slow method for reading contents information here. auto pa = openPayloadArchive (); contentsL = pa.readContents (); contentsRead = true; return contentsL; } // use the md5sums file of the .deb control archive to determine // the contents of this package. // this is way faster than going through the payload directly, and // has the same accuracy. auto ca = openControlArchive (); const(ubyte)[] md5sumsData; try { md5sumsData = ca.readData ("./md5sums"); } catch (Exception e) { logWarning ("Could not read md5sums file for package %s: %s", this.id, e.msg); return []; } auto md5sums = cast(string) md5sumsData; try { md5sums = md5sums.toUTF8; } catch (Exception e) { logError ("Could not decode md5sums file for package %s: %s", this.id, e.msg); return []; } auto contentsAppender = appender!(string[]); foreach (line; md5sums.splitLines ()) { auto parts = line.split (" "); if (parts.length <= 0) continue; string c = join (parts[1..$], " "); contentsAppender.put ("/" ~ c); } contentsL = contentsAppender.data; contentsRead = true; return contentsL; } override final void close () { try { if (std.file.exists (tmpDir)) rmdirRecurse (tmpDir); dataArchive = null; controlArchive = null; } catch (Throwable) { // we ignore any error } } } appstream-generator-0.6.8/src/asgen/backends/debian/debpkgindex.d000066400000000000000000000253021320016272000250110ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.debian.debpkgindex; import std.stdio; import std.path; import std.string; import std.algorithm : remove; import std.array : appender; import std.conv : to; static import std.file; import asgen.logging; import asgen.backends.interfaces; import asgen.backends.debian.tagfile; import asgen.backends.debian.debpkg; import asgen.backends.debian.debutils; import asgen.config; import asgen.utils : escapeXml, getFileContents, isRemote; class DebianPackageIndex : PackageIndex { private: string rootDir; Package[][string] pkgCache; bool[string] indexChanged; protected: string tmpDir; public: this (string dir) { this.rootDir = dir; if (!dir.isRemote && !std.file.exists (dir)) throw new Exception ("Directory '%s' does not exist.".format (dir)); auto conf = Config.get (); tmpDir = buildPath (conf.getTmpDir, dir.baseName); } final void release () { pkgCache = null; indexChanged = null; } private final immutable(string[]) findTranslations (const string suite, const string section) { import std.regex : matchFirst, regex; immutable inRelease = buildPath (rootDir, "dists", suite, "InRelease"); auto translationregex = r"%s/i18n/Translation-(\w+)$".format (section).regex; bool[string] ret; try { synchronized (this) { const inReleaseContents = getFileContents (inRelease); foreach (const ref entry; inReleaseContents) { auto match = entry.matchFirst (translationregex); if (match.empty) continue; ret[match[1]] = true; } } } catch (Exception ex) { logWarning ("Could not get %s, will assume 'en' is available.", inRelease); return ["en"]; } return cast(immutable) ret.keys; } private final void loadPackageLongDescs (DebPackage[string] pkgs, string suite, string section) { immutable langs = findTranslations (suite, section); logDebug ("Found translations for: %s", langs.join(", ")); foreach (const ref lang; langs) { string fname; immutable fullPath = buildPath ("dists", suite, section, "i18n", /* here we explicitly substitute a * "%s", because * downloadIfNecessary will put the * file extension there */ "Translation-%s.%s".format(lang, "%s")); try { synchronized (this) { fname = downloadIfNecessary (rootDir, tmpDir, fullPath); } } catch (Exception ex) { logDebug ("No translations for %s in %s/%s", lang, suite, section); continue; } auto tagf = new TagFile (); tagf.open (fname); do { auto pkgname = tagf.readField ("Package"); auto rawDesc = tagf.readField ("Description-%s".format (lang)); if (!pkgname) continue; if (!rawDesc) continue; auto pkgP = (pkgname in pkgs); if (pkgP is null) continue; auto split = rawDesc.split ("\n"); if (split.length < 2) continue; if (lang == "en") (*pkgP).setSummary (split[0], "C"); (*pkgP).setSummary (split[0], lang); // NOTE: .remove() removes the element, but does not alter the // length of the array. Bug? (this is why we slice the array // here) split = split[1..$]; // TODO: We actually need a Markdown-ish parser here if we want // to support listings in package descriptions properly. auto description = appender!string; description ~= "

"; bool first = true; foreach (l; split) { if (l.strip () == ".") { description ~= "

\n

"; first = true; continue; } if (first) first = false; else description ~= " "; description ~= escapeXml (l); } description ~= "

"; if (lang == "en") (*pkgP).setDescription (description.data, "C"); (*pkgP).setDescription (description.data, lang); } while (tagf.nextSection ()); } } private final string getIndexFile (string suite, string section, string arch) { immutable path = buildPath ("dists", suite, section, "binary-%s".format (arch)); synchronized (this) { return downloadIfNecessary (rootDir, tmpDir, buildPath (path, "Packages.%s")); } } protected DebPackage newPackage (string name, string ver, string arch) { return new DebPackage (name, ver, arch); } private final DebPackage[] loadPackages (string suite, string section, string arch) { auto indexFname = getIndexFile (suite, section, arch); if (!std.file.exists (indexFname)) { logWarning ("Archive package index file '%s' does not exist.", indexFname); return []; } auto tagf = new TagFile (); tagf.open (indexFname); logDebug ("Opened: %s", indexFname); DebPackage[string] pkgs; do { import std.algorithm : map; import std.array : array; auto name = tagf.readField ("Package"); auto ver = tagf.readField ("Version"); auto fname = tagf.readField ("Filename"); if (!name) continue; auto pkg = newPackage (name, ver, arch); pkg.filename = buildPath (rootDir, fname); pkg.maintainer = tagf.readField ("Maintainer"); immutable decoders = tagf.readField("Gstreamer-Decoders") .split(";") .map!strip.array; immutable encoders = tagf.readField("Gstreamer-Encoders") .split(";") .map!strip.array; immutable elements = tagf.readField("Gstreamer-Elements") .split(";") .map!strip.array; immutable uri_sinks = tagf.readField("Gstreamer-Uri-Sinks") .split(";") .map!strip.array; immutable uri_sources = tagf.readField("Gstreamer-Uri-Sources") .split(";") .map!strip.array; pkg.gst = new GStreamer(decoders, encoders, elements, uri_sinks, uri_sources); if (!pkg.isValid ()) { logWarning ("Found invalid package (%s)! Skipping it.", pkg.toString ()); continue; } // filter out the most recent package version in the packages list auto epkgP = name in pkgs; if (epkgP !is null) { auto epkg = *epkgP; if (compareVersions (epkg.ver, pkg.ver) > 0) continue; } pkgs[name] = pkg; } while (tagf.nextSection ()); // load long descriptions loadPackageLongDescs (pkgs, suite, section); return pkgs.values; } Package[] packagesFor (string suite, string section, string arch) { immutable id = "%s/%s/%s".format (suite, section, arch); if (id !in pkgCache) { auto pkgs = loadPackages (suite, section, arch); synchronized (this) pkgCache[id] = to!(Package[]) (pkgs); } return pkgCache[id]; } final bool hasChanges (DataStore dstore, string suite, string section, string arch) { import std.json; auto indexFname = getIndexFile (suite, section, arch); // if the file doesn't exit, we will emit a warning later anyway, so we just ignore this here if (!std.file.exists (indexFname)) return true; // check our cache on whether the index had changed if (indexFname in indexChanged) return indexChanged[indexFname]; std.datetime.SysTime mtime; std.datetime.SysTime atime; std.file.getTimes (indexFname, atime, mtime); auto currentTime = mtime.toUnixTime (); auto repoInfo = dstore.getRepoInfo (suite, section, arch); scope (exit) { repoInfo.object["mtime"] = JSONValue (currentTime); dstore.setRepoInfo (suite, section, arch, repoInfo); } if ("mtime" !in repoInfo.object) { indexChanged[indexFname] = true; return true; } auto pastTime = repoInfo["mtime"].integer; if (pastTime != currentTime) { indexChanged[indexFname] = true; return true; } indexChanged[indexFname] = false; return false; } } unittest { import std.algorithm.sorting : sort; import asgen.utils : getTestSamplesDir; writeln ("TEST: ", "DebianPackageIndex"); auto pi = new DebianPackageIndex (buildPath (getTestSamplesDir (), "debian")); assert (sort(pi.findTranslations ("sid", "main").dup) == sort(["en", "ca", "cs", "da", "de", "de_DE", "el", "eo", "es", "eu", "fi", "fr", "hr", "hu", "id", "it", "ja", "km", "ko", "ml", "nb", "nl", "pl", "pt", "pt_BR", "ro", "ru", "sk", "sr", "sv", "tr", "uk", "vi", "zh", "zh_CN", "zh_TW"])); } appstream-generator-0.6.8/src/asgen/backends/debian/debutils.d000066400000000000000000000174231320016272000243450ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * Copyright (C) The APT development team. * Copyright (C) 2016 Canonical Ltd * Author(s): Iain Lane * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.debian.debutils; import std.string; static import std.file; import asgen.logging; import asgen.utils : downloadFile, isRemote; /** * If prefix is remote, download the first of (prefix + suffix).{xz,bz2,gz}, * otherwise check if any of (prefix + suffix).{xz,bz2,gz} exists. * * Returns: Path to the file, which is guaranteed to exist. * * Params: * prefix = First part of the address, i.e. * "http://ftp.debian.org/debian/" or "/srv/mirrors/debian/" * destPrefix = If the file is remote, the directory to save it under, * which is created if necessary. * suffix = the rest of the address, so that (prefix + * suffix).format({xz,bz2,gz}) is a full path or URL, i.e. * "dists/unstable/main/binary-i386/Packages.%s". The suffix must * contain exactly one "%s"; this function is only suitable for * finding `.xz`, `.bz2` and `.gz` files. */ immutable (string) downloadIfNecessary (const string prefix, const string destPrefix, const string suffix) { import std.net.curl; import std.path; immutable exts = ["xz", "bz2", "gz"]; foreach (ref ext; exts) { immutable fileName = format (buildPath (prefix, suffix), ext); immutable destFileName = format (buildPath (destPrefix, suffix), ext); if (fileName.isRemote) { try { /* This should use download(), but that doesn't throw errors */ downloadFile (fileName, destFileName); return destFileName; } catch (CurlException ex) { logDebug ("Could not download: %s", ex.msg); } } else { if (std.file.exists (fileName)) return fileName; } } /* all extensions failed, so we failed */ throw new Exception (format ("Could not obtain any file matching %s", buildPath (prefix, suffix))); } /** * This compares a fragment of the version. This is a slightly adapted * version of what dpkg uses in dpkg/lib/dpkg/version.c. * In particular, the a | b = NULL check is removed as we check this in the * caller, we use an explicit end for a | b strings and we check ~ explicit. */ private int order (char c) pure { import std.ascii; if (c.isDigit) return 0; else if (c.isAlpha) return c; else if (c == '~') return -1; else if (c) return c + 256; else return 0; } /** * Iterate over the whole string * What this does is to split the whole string into groups of * numeric and non numeric portions. For instance: * a67bhgs89 * Has 4 portions 'a', '67', 'bhgs', '89'. A more normal: * 2.7.2-linux-1 * Has '2', '.', '7', '.' ,'-linux-','1' */ private int cmpFragment (const(immutable(char)*) a, const(immutable(char)*) aEnd, const(immutable(char)*) b, const(immutable(char)*) bEnd) @trusted pure { import std.ascii; immutable(char) *lhs = a; immutable(char) *rhs = b; while (lhs != aEnd && rhs != bEnd) { int first_diff = 0; while (lhs != aEnd && rhs != bEnd && (!(*lhs).isDigit || !(*rhs).isDigit)) { int vc = order (*lhs); int rc = order (*rhs); if (vc != rc) return vc - rc; ++lhs; ++rhs; } while (*lhs == '0') ++lhs; while (*rhs == '0') ++rhs; while ((*lhs).isDigit && (*rhs).isDigit) { if (!first_diff) first_diff = *lhs - *rhs; ++lhs; ++rhs; } if ((*lhs).isDigit) return 1; if ((*rhs).isDigit) return -1; if (first_diff) return first_diff; } // The strings must be equal if (lhs == aEnd && rhs == bEnd) return 0; // lhs is shorter if (lhs == aEnd) { if (*rhs == '~') return 1; return -1; } // rhs is shorter if (rhs == bEnd) { if (*lhs == '~') return -1; return 1; } // Shouldn't happen return 1; } // import from string.h, needs glibc private extern(C) void *memrchr (const void *s, int c, size_t n) @system pure; /** * Compare two Debian-style version numbers. */ int compareVersions (const string a, const string b) @trusted pure { import core.stdc.string; immutable(char) *ac = a.toStringz; immutable(char) *bc = b.toStringz; immutable(char*) aEnd = ac + a.length; immutable(char*) bEnd = bc + b.length; // Strip off the epoch and compare it auto lhs = cast(immutable(char)*) memchr (ac, ':', aEnd - ac); auto rhs = cast(immutable(char)*) memchr (bc, ':', bEnd - bc); if (lhs is null) lhs = ac; if (rhs is null) rhs = bc; // Special case: a zero epoch is the same as no epoch, // so remove it. if (lhs != ac) { for (; *ac == '0'; ++ac) {} if (ac == lhs) { ++ac; ++lhs; } } if (rhs != bc) { for (; *bc == '0'; ++bc) {} if (bc == rhs) { ++bc; ++rhs; } } // Compare the epoch auto res = cmpFragment (ac, lhs, bc, rhs); if (res != 0) return res; // Skip the : if (lhs != ac) lhs++; if (rhs != bc) rhs++; // Find the last - auto dlhs = cast(immutable(char)*) memrchr (lhs, '-', aEnd - lhs); auto drhs = cast(immutable(char)*) memrchr (rhs, '-', bEnd - rhs); if (dlhs is null) dlhs = aEnd; if (drhs is null) drhs = bEnd; // Compare the main version res = cmpFragment (lhs, dlhs, rhs, drhs); if (res != 0) return res; // Skip the - if (dlhs != lhs) dlhs++; if (drhs != rhs) drhs++; // no debian revision need to be treated like -0 if (*(dlhs - 1) == '-' && *(drhs - 1) == '-') { return cmpFragment (dlhs, aEnd, drhs, bEnd); } else if (*(dlhs - 1) == '-') { immutable(char)* zeroZ = "0"; return cmpFragment (dlhs, aEnd, zeroZ, zeroZ + 1); } else if (*(drhs - 1) == '-') { immutable(char)* zeroZ = "0"; return cmpFragment (zeroZ, zeroZ + 1, drhs, bEnd); } else { return 0; } } unittest { import std.stdio : writeln; writeln ("TEST: ", "DebianUtils"); assert (compareVersions ("6", "8") < 0); assert (compareVersions ("0.6.12b-d", "0.6.12a") > 0); assert (compareVersions ("7.4", "7.4") == 0); assert (compareVersions ("ab.d", "ab.f") < 0); assert (compareVersions ("0.6.16", "0.6.14") > 0); assert (compareVersions ("3.0.rc2", "3.0.0") > 0); assert (compareVersions ("3.0.0~rc2", "3.0.0") < 0); assert (compareVersions ("4:5.6-2", "8.0-6") > 0); assert (compareVersions ("1:1.0-4", "3:0.8-2") < 0); } appstream-generator-0.6.8/src/asgen/backends/debian/package.d000066400000000000000000000016471320016272000241260ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.debian; public import asgen.backends.debian.debpkg; public import asgen.backends.debian.debpkgindex; appstream-generator-0.6.8/src/asgen/backends/debian/tagfile.d000066400000000000000000000057001320016272000241400ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.debian.tagfile; import std.stdio; import std.string; import asgen.zarchive; import asgen.logging; final class TagFile { private: string[] content; uint pos; public: this () { } void open (string fname) { content = null; string data; try { data = decompressFile (fname); } catch (Exception e) { throw e; } content = splitLines (data); pos = 0; } void first () { pos = 0; } bool nextSection () { bool breakNext = false; auto clen = content.length; if (pos >= clen) return false; uint i; for (i = pos; i < clen; i++) { if (content[i] == "") { pos = i + 1; breakNext = true; } else if (breakNext) { break; } } // check if we reached the end of this file if (i == clen) pos = cast(uint) clen; if (pos >= clen) return false; return true; } string readField (string name) { auto clen = content.length; for (auto i = pos; i < clen; i++) { if (content[i] == "") break; auto fdata = chompPrefix (content[i], name ~ ":"); if (fdata == content[i]) continue; if ((i+1 >= clen) || (!startsWith (content[i+1], " "))) { // we have a single-line field return strip (fdata); } else { // we have a multi-line field auto fdata_ml = strip (fdata); for (auto j = i+1; j < clen; j++) { auto slice = chompPrefix (content[j], " "); if (slice == content[j]) break; if (fdata_ml == "") fdata_ml = slice; else fdata_ml ~= "\n" ~ slice; } return fdata_ml; } } // we found nothing return null; } } appstream-generator-0.6.8/src/asgen/backends/dummy/000077500000000000000000000000001320016272000222675ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/backends/dummy/dummypkg.d000066400000000000000000000043261320016272000242760ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.dummy.dummypkg; import std.stdio; import std.string; import std.array : empty; import asgen.backends.interfaces; import asgen.logging; final class DummyPackage : Package { private: string pkgname; string pkgver; string pkgarch; string pkgmaintainer; string[string] desc; string testPkgFname; public: @property override string name () const { return pkgname; } @property override string ver () const { return pkgver; } @property override string arch () const { return pkgarch; } @property override const(string[string]) description () const { return desc; } override @property string filename () const { return testPkgFname; } @property void filename (string fname) { testPkgFname = fname; } override @property string maintainer () const { return pkgmaintainer; } @property void maintainer (string maint) { pkgmaintainer = maint; } this (string pname, string pver, string parch) { pkgname = pname; pkgver = pver; pkgarch = parch; } ~this () { } void setDescription (string text, string locale) { desc[locale] = text; } override ubyte[] getFileData (string fname) { return ['N', 'O', 'T', 'H', 'I', 'N', 'G']; } @property override string[] contents () { return ["NOTHING1", "NOTHING2"]; } override void close () { } } appstream-generator-0.6.8/src/asgen/backends/dummy/package.d000066400000000000000000000016431320016272000240330ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.dummy; public import asgen.backends.dummy.dummypkg; public import asgen.backends.dummy.pkgindex; appstream-generator-0.6.8/src/asgen/backends/dummy/pkgindex.d000066400000000000000000000027141320016272000242510ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.dummy.pkgindex; import std.stdio; import std.path; import std.string; import std.algorithm : remove; import asgen.logging; import asgen.backends.interfaces; import asgen.backends.dummy.dummypkg; final class DummyPackageIndex : PackageIndex { private: Package[][string] pkgCache; public: this (string dir) { } void release () { pkgCache = null; } Package[] packagesFor (string suite, string section, string arch) { return [new DummyPackage ("test", "1.0", "amd64")]; } bool hasChanges (DataStore dstore, string suite, string section, string arch) { return true; } } appstream-generator-0.6.8/src/asgen/backends/interfaces.d000066400000000000000000000130111320016272000234200ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.interfaces; import appstream.Component; import glib.KeyFile; import std.string; import std.container; public import asgen.datastore; class GStreamer { immutable string[] decoders; immutable string[] encoders; immutable string[] elements; immutable string[] uri_sinks; immutable string[] uri_sources; @property @safe pure bool isNotEmpty() { return !(decoders.empty && encoders.empty && elements.empty && uri_sinks.empty && uri_sources.empty); } this () { decoders = encoders = elements = uri_sinks = uri_sources = []; } this (immutable string[] decoders, immutable string[] encoders, immutable string[] elements, immutable string[] uri_sinks, immutable string[] uri_sources) { this.decoders = decoders; this.encoders = encoders; this.elements = elements; this.uri_sinks = uri_sinks; this.uri_sources = uri_sources; } } /** * Represents a distribution package in the generator. */ abstract class Package { @property string name () const @safe pure; @property string ver () const @safe pure; @property string arch () const @safe pure; @property string maintainer () const; /** * A associative array containing package descriptions. * Key is the language (or locale), value the description. * * E.g.: ["en": "A description.", "de": "Eine Beschreibung"] */ @property const(string[string]) description () const; /** * A associative array containing package summaries. * Key is the language (or locale), value the summary. * * E.g.: ["en": "foo the bar"] */ @property const(string[string]) summary () const { return (string[string]).init; }; /** * Filename of the package. This string is only used for * issue reporting and other information, the file is never * accessed directly (all data is retrieved via getFileData()) */ @property string filename () const; /** * A list payload files this package contains. */ @property string[] contents (); /** * Obtain data for a specific file in the package. */ abstract const(ubyte)[] getFileData (string fname); /** * Close the package. This function is called when we will * no longer request any file data from this package. */ abstract void close () {}; @property GStreamer gst () { return new GStreamer(); } /** * Retrieve backend-specific translations. * * (currently only used by the Ubuntu backend) */ string[string] getDesktopFileTranslations (KeyFile desktopFile, const string text) { return null; } private string pkid; /** * Get the unique identifier for this package. * The ID is supposed to be unique per backend, it should never appear * multiple times in suites/sections. */ @property final string id () @safe pure { import std.array : empty; if (pkid.empty) pkid = "%s/%s/%s".format (this.name, this.ver, this.arch); return pkid; } /** * Check if the package is valid. * A Package must at least have a name, version and architecture defined. */ @safe pure final bool isValid () { import std.array : empty; return (!name.empty) && (!ver.empty) && (!arch.empty); } @safe pure override string toString () { return id; } } /** * An index of information about packages in a distribution. */ interface PackageIndex { /** * Called after a set of operations has completed, which allows the index to * release memory it might have allocated for cached data, or delete temporary * files. **/ void release (); /** * Get a list of packages for the given suite/section/arch triplet. * The PackageIndex should cache the data if obtaining it is an expensive * operation, since the generator might query the data multiple times. **/ Package[] packagesFor (string suite, string section, string arch); /** * Check if the index for the given suite/section/arch triplet has changed since * the last generator run. The index can use the (get/set)RepoInfo methods on DataCache * to store mtime or checksum data for the given suite. * For the lifetime of the PackagesIndex, this method must return the same result, * which means an internal cache is useful. */ bool hasChanges (DataStore dstore, string suite, string section, string arch); } appstream-generator-0.6.8/src/asgen/backends/rpmmd/000077500000000000000000000000001320016272000222535ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/backends/rpmmd/package.d000066400000000000000000000001721320016272000240130ustar00rootroot00000000000000 module asgen.backends.rpmmd; public import asgen.backends.rpmmd.rpmpkg; public import asgen.backends.rpmmd.rpmpkgindex; appstream-generator-0.6.8/src/asgen/backends/rpmmd/rpmpkg.d000066400000000000000000000050571320016272000237270ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.rpmmd.rpmpkg; import std.stdio; import std.string; import std.array : empty; import asgen.logging; import asgen.zarchive; import asgen.backends.interfaces; final class RPMPackage : Package { private: string pkgname; string pkgver; string pkgarch; string pkgmaintainer; string[string] desc; string[string] summ; string pkgFname; string[] contentsL; ArchiveDecompressor archive; public: override @property string name () const { return pkgname; } @property void name (string val) { pkgname = val; } override @property string ver () const { return pkgver; } @property void ver (string val) { pkgver = val; } override @property string arch () const { return pkgarch; } @property void arch (string val) { pkgarch = val; } override @property const(string[string]) description () const { return desc; } override @property string filename () const { return pkgFname; } @property void filename (string fname) { pkgFname = fname; } override @property string maintainer () const { return pkgmaintainer; } @property void maintainer (string maint) { pkgmaintainer = maint; } void setDescription (string text, string locale) { desc[locale] = text; } void setSummary (string text, string locale) { summ[locale] = text; } override const(ubyte)[] getFileData (string fname) { if (!archive.isOpen) archive.open (this.filename); return archive.readData (fname); } @property override string[] contents () { return contentsL; } @property void contents (string[] c) { contentsL = c; } override void close () { } } appstream-generator-0.6.8/src/asgen/backends/rpmmd/rpmpkgindex.d000066400000000000000000000160551320016272000247570ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.rpmmd.rpmpkgindex; import std.stdio : writeln; import std.path : buildPath; import std.array : appender, empty; import std.string : format; import std.algorithm : canFind, endsWith; import std.conv : to; import std.xml; static import std.file; import asgen.logging; import asgen.backends.interfaces; import asgen.backends.rpmmd.rpmpkg; final class RPMPackageIndex : PackageIndex { private: string rootDir; Package[][string] pkgCache; public: this (string dir) { this.rootDir = dir; if (!std.file.exists (dir)) throw new Exception ("Directory '%s' does not exist.", dir); } void release () { pkgCache = null; } private void setPkgDescription (RPMPackage pkg, string pkgDesc) { if (pkgDesc is null) return; auto desc = "

%s

".format (pkgDesc); pkg.setDescription (desc, "C"); } private RPMPackage[] loadPackages (string suite, string section, string arch) { auto repoRoot = buildPath (rootDir, suite, section, arch, "os"); auto primaryIndexFiles = appender!(string[]); auto filelistFiles = appender!(string[]); auto repoMdIndexContent = cast(string) std.file.read (buildPath (repoRoot, "repodata", "repomd.xml")); auto indexXml = new DocumentParser (repoMdIndexContent); indexXml.onStartTag["data"] = (ElementParser xml) { immutable dataType = xml.tag.attr["type"]; if (dataType == "primary") { xml.onStartTag["location"] = (ElementParser x) { primaryIndexFiles ~= x.tag.attr["href"]; }; xml.parse (); } else if (dataType == "filelists") { xml.onStartTag["location"] = (ElementParser x) { filelistFiles ~= x.tag.attr["href"]; }; xml.parse (); } }; indexXml.parse(); // package-id -> RPMPackage RPMPackage[string] pkgMap; // parse the primary metadata foreach (ref primaryFile; primaryIndexFiles.data) { immutable metaFname = buildPath (repoRoot, primaryFile); string data; if (primaryFile.endsWith (".xml")) { data = cast(string) std.file.read (metaFname); } else { import asgen.zarchive : decompressFile; data = decompressFile (metaFname); } auto pkgXml = new DocumentParser (data); pkgXml.onStartTag["package"] = (ElementParser xml) { // make sure we only check RPM packages if (xml.tag.attr["type"] != "rpm") return; auto pkg = new RPMPackage; pkg.maintainer = "None"; xml.onEndTag["name"] = (in Element e) { pkg.name = e.text; }; xml.onEndTag["arch"] = (in Element e) { pkg.arch = e.text; }; xml.onEndTag["summary"] = (in Element e) { pkg.setSummary (e.text, "C"); }; xml.onEndTag["description"] = (in Element e) { pkg.setDescription (e.text, "C"); }; xml.onEndTag["packager"] = (in Element e) { pkg.maintainer = e.text; }; xml.onStartTag["version"] = (ElementParser x) { immutable epoch = x.tag.attr["epoch"]; immutable upstream_ver = x.tag.attr["ver"]; immutable rel = x.tag.attr["rel"]; if ((epoch == "0") || (epoch.empty)) pkg.ver = "%s-%s".format (upstream_ver, rel); else pkg.ver = "%s:%s-%s".format (epoch, upstream_ver, rel); }; xml.onStartTag["location"] = (ElementParser x) { pkg.filename = buildPath (repoRoot, x.tag.attr["href"]); }; string pkgidCS; xml.onEndTag["checksum"] = (in Element e) { // we are only interested in the package-id here if (e.tag.attr["pkgid"] != "YES") return; pkgidCS = e.text; }; xml.parse (); if (pkgidCS.empty) { logWarning ("Found package '%s' in '%s' without suitable pkgid. Ignoring it.", pkg.name, primaryFile); return; } pkgMap[pkgidCS] = pkg; }; pkgXml.parse(); } pkgMap.rehash; // read the filelists foreach (ref filelistFile; filelistFiles.data) { immutable flistFname = buildPath (repoRoot, filelistFile); string data; if (filelistFile.endsWith (".xml")) { data = cast(string) std.file.read (flistFname); } else { import asgen.zarchive : decompressFile; data = decompressFile (flistFname); } auto flXml = new DocumentParser (data); flXml.onStartTag["package"] = (ElementParser xml) { immutable pkgid = xml.tag.attr["pkgid"]; auto pkgP = pkgid in pkgMap; if (pkgP is null) return; auto pkg = *pkgP; auto contents = appender!(string[]); xml.onEndTag["file"] = (in Element e) { contents ~= e.text; }; xml.parse (); pkg.contents = contents.data; }; flXml.parse(); } return pkgMap.values; } Package[] packagesFor (string suite, string section, string arch) { immutable id = "%s-%s-%s".format (suite, section, arch); if (id !in pkgCache) { auto pkgs = loadPackages (suite, section, arch); synchronized (this) pkgCache[id] = to!(Package[]) (pkgs); } return pkgCache[id]; } bool hasChanges (DataStore dstore, string suite, string section, string arch) { return true; } } unittest { import std.algorithm.sorting : sort; import asgen.utils : getTestSamplesDir; writeln ("TEST: ", "RpmMDPackageIndex"); auto pi = new RPMPackageIndex (buildPath (getTestSamplesDir (), "rpmmd")); auto pkgs = pi.loadPackages ("26", "Workstation", "x86_64"); assert (pkgs.length == 4); } appstream-generator-0.6.8/src/asgen/backends/ubuntu/000077500000000000000000000000001320016272000224565ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/backends/ubuntu/package.d000066400000000000000000000016471320016272000242260ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.ubuntu; public import asgen.backends.ubuntu.ubupkg; public import asgen.backends.ubuntu.ubupkgindex; appstream-generator-0.6.8/src/asgen/backends/ubuntu/ubupkg.d000066400000000000000000000147161320016272000241310ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd * Author: Iain Lane * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.ubuntu.ubupkg; import std.container : Array; import std.path : buildPath; import std.file : mkdirRecurse; import std.conv : to; import glib.Internationalization; import glib.KeyFile; import appstream.Component; import asgen.logging; import asgen.utils : DESKTOP_GROUP; import asgen.backends.debian.debpkg; import asgen.backends.interfaces; extern (C) char *bindtextdomain (const char *domainname, const char *dirName) nothrow @nogc; final class UbuntuPackage : DebPackage { this (string pname, string pver, string parch, string globalTmpDir, ref Array!Package langpacks) { this.globalTmpDir = globalTmpDir; this.langpackDir = buildPath (globalTmpDir, "langpacks"); this.localeDir = buildPath (langpackDir, "locales"); this.langpacks = langpacks; super (pname, pver, parch); } override string[string] getDesktopFileTranslations (KeyFile desktopFile, const string text) { string langpackdomain; try { langpackdomain = desktopFile.getString (DESKTOP_GROUP, "X-Ubuntu-Gettext-Domain"); } catch (Throwable) { try { langpackdomain = desktopFile.getString (DESKTOP_GROUP, "X-GNOME-Gettext-Domain"); } catch (Throwable) { return null; } } logDebug ("%s has langpack domain %s", name, langpackdomain); synchronized { extractLangpacks (); return getTranslations (langpackdomain, text); } } private: string globalTmpDir; string langpackDir; string localeDir; string[] langpackLocales; Array!Package langpacks; private void extractLangpacks () { import std.algorithm : filter, map; import std.array : appender, array, split; import std.file : dirEntries, exists, SpanMode, readText; import std.parallelism : parallel; import std.path : baseName; import std.process : Pid, spawnProcess, wait; import std.string : splitLines, startsWith; auto path = buildPath (langpackDir, "usr", "share", "locale-langpack"); if (!langpackDir.exists) { bool[string] extracted; langpackDir.mkdirRecurse (); foreach (ref pkg; langpacks) { if (pkg.name in extracted) continue; auto upkg = to!UbuntuPackage (pkg); logDebug ("Extracting %s", pkg.name); upkg.extractPackage (langpackDir); extracted[pkg.name] = true; } // get back the memory langpacks.clear; auto supportedd = buildPath (langpackDir, "var", "lib", "locales", "supported.d"); localeDir.mkdirRecurse (); foreach (locale; parallel (supportedd.dirEntries (SpanMode.shallow), 5)) { foreach (ref line; locale.readText.splitLines) { auto components = line.split (" "); auto localecharset = components[0].split ("."); auto outdir = buildPath (localeDir, components[0]); logDebug ("Generating locale in %s", outdir); auto pid = spawnProcess (["/usr/bin/localedef", "--no-archive", "-i", localecharset[0], "-c", "-f", components[1], outdir]); scope (exit) wait (pid); } } } else { // we don't need it; we've already extracted the langpacks langpacks.clear; } if (langpackLocales is null) langpackLocales = localeDir.dirEntries (SpanMode.shallow) .filter!(f => f.isDir) .map!(f => f.name.baseName) .array; } string[string] getTranslations (const string domain, const string text) { import core.stdc.locale; import core.stdc.string : strdup; import std.c.stdlib : getenv, setenv, unsetenv; import std.string : fromStringz, toStringz; char *[char *] env; foreach (ref var; ["LC_ALL", "LANG", "LANGUAGE", "LC_MESSAGES"]) { auto value = getenv (var.toStringz); if (value !is null) { env[var.toStringz] = getenv (var.toStringz).strdup; unsetenv (var.toStringz); } } scope (exit) { foreach (key, val; env) setenv (key, val, false); } setenv ("LOCPATH", localeDir.toStringz, true); auto initialLocale = setlocale (LC_ALL, ""); scope(exit) setlocale (LC_ALL, initialLocale); auto dir = buildPath (langpackDir, "usr", "share", "locale-langpack"); string[string] ret; foreach (ref locale; langpackLocales) { setlocale (LC_ALL, locale.toStringz); bindtextdomain (domain.toStringz, dir.toStringz); auto translatedtext = Internationalization.dgettext (domain, text); if (text != translatedtext) ret[locale] = translatedtext; } return ret; } } appstream-generator-0.6.8/src/asgen/backends/ubuntu/ubupkgindex.d000066400000000000000000000043041320016272000251510ustar00rootroot00000000000000/* * Copyright (C) 2016 Canonical Ltd * Author: Iain Lane * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.backends.ubuntu.ubupkgindex; import std.container : Array, make; import std.array : appender; import asgen.backends.debian; import asgen.backends.interfaces; import asgen.backends.ubuntu.ubupkg; final class UbuntuPackageIndex : DebianPackageIndex { private: Array!Package langpacks; public: this (string dir) { /* * UbuntuPackage needs to extract the langpacks, so we give it an array * of langpacks. There is a small overhead when computing this array * which might be unnecessary if no processed packages are using * langpacks, but otherwise we need to keep a reference to all packages * around, which is very expensive. */ langpacks = make!(Array!Package); super (dir); } override DebPackage newPackage (string name, string ver, string arch) { return new UbuntuPackage (name, ver, arch, tmpDir, langpacks); } override Package[] packagesFor (string suite, string section, string arch) { import std.string : startsWith; auto pkgs = super.packagesFor (suite, section, arch); auto pkgslangpacks = appender!(Package[]); foreach (ref pkg; pkgs) { if (pkg.name.startsWith ("language-pack-")) pkgslangpacks ~= pkg; } langpacks ~= pkgslangpacks.data; return pkgs; } } appstream-generator-0.6.8/src/asgen/bindings/000077500000000000000000000000001320016272000211575ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/bindings/appstream_utils.d000066400000000000000000000024011320016272000245350ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.appstream_utils; import appstream.c.types; extern(C): nothrow: @nogc: @system: bool as_utils_is_tld (const char *tld) pure; bool as_utils_is_category_name (const char *category_name) pure; const(char) *as_format_version_to_string (FormatVersion ver) pure; FormatVersion as_format_version_from_string (const char *version_str) pure; bool as_license_is_metadata_license (const char *license) pure; const(char) *as_get_appstream_version () pure; appstream-generator-0.6.8/src/asgen/bindings/cairo.d000066400000000000000000000105751320016272000224310ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.cairo; extern(C): nothrow: @nogc: static if (!is(typeof(usize))) private alias usize = size_t; struct _cairo {} alias cairo_p = _cairo*; struct _cairo_surface {} alias cairo_surface_p = _cairo_surface*; struct _cairo_font_face {} alias cairo_font_face_p = _cairo_font_face*; struct cairo_text_extents_t { double x_bearing; double y_bearing; double width; double height; double x_advance; double y_advance; }; enum cairo_status_t { STATUS_SUCCESS = 0, STATUS_NO_MEMORY, STATUS_INVALID_RESTORE, STATUS_INVALID_POP_GROUP, STATUS_NO_CURRENT_POINT, STATUS_INVALID_MATRIX, STATUS_INVALID_STATUS, STATUS_NULL_POINTER, STATUS_INVALID_STRING, STATUS_INVALID_PATH_DATA, STATUS_READ_ERROR, STATUS_WRITE_ERROR, STATUS_SURFACE_FINISHED, STATUS_SURFACE_TYPE_MISMATCH, STATUS_PATTERN_TYPE_MISMATCH, STATUS_INVALID_CONTENT, STATUS_INVALID_FORMAT, STATUS_INVALID_VISUAL, STATUS_FILE_NOT_FOUND, STATUS_INVALID_DASH, STATUS_INVALID_DSC_COMMENT, STATUS_INVALID_INDEX, STATUS_CLIP_NOT_REPRESENTABLE, STATUS_TEMP_FILE_ERROR, STATUS_INVALID_STRIDE, STATUS_FONT_TYPE_MISMATCH, STATUS_USER_FONT_IMMUTABLE, STATUS_USER_FONT_ERROR, STATUS_NEGATIVE_COUNT, STATUS_INVALID_CLUSTERS, STATUS_INVALID_SLANT, STATUS_INVALID_WEIGHT, STATUS_INVALID_SIZE, STATUS_USER_FONT_NOT_IMPLEMENTED, STATUS_DEVICE_TYPE_MISMATCH, STATUS_DEVICE_ERROR, STATUS_INVALID_MESH_CONSTRUCTION, STATUS_DEVICE_FINISHED, STATUS_JBIG2_GLOBAL_MISSING, STATUS_LAST_STATUS }; enum cairo_format_t { FORMAT_INVALID = -1, FORMAT_ARGB32 = 0, FORMAT_RGB24 = 1, FORMAT_A8 = 2, FORMAT_A1 = 3, FORMAT_RGB16_565 = 4, FORMAT_RGB30 = 5 }; // Context cairo_p cairo_create (cairo_surface_p target); cairo_p cairo_reference (cairo_p cr); void cairo_destroy (cairo_p cr); void cairo_set_source_surface (cairo_p cr, cairo_surface_p surface, double x, double y); void cairo_paint (cairo_p cr); void cairo_save (cairo_p cr); void cairo_restore (cairo_p cr); // Surface cairo_surface_p cairo_image_surface_create (cairo_format_t format, int width, int height); cairo_surface_p cairo_image_surface_create_from_png (const(char) *filename); // Toy API void cairo_surface_destroy (cairo_surface_p surface); cairo_status_t cairo_surface_status (cairo_surface_p surface); int cairo_image_surface_get_width (cairo_surface_p surface); int cairo_image_surface_get_height (cairo_surface_p surface); cairo_status_t cairo_surface_write_to_png (cairo_surface_p surface, const(char) *filename); // Toy API void cairo_surface_flush (cairo_surface_p surface); ubyte* cairo_image_surface_get_data (cairo_surface_p surface); // Transformations void cairo_scale (cairo_p cr, double sx, double sy); void cairo_translate (cairo_p cr, double tx, double ty); // Drawing void cairo_move_to (cairo_p cr, double x, double y); void cairo_set_source_rgb (cairo_p cr, double red, double green, double blue); // Fonts import asgen.bindings.freetype; cairo_font_face_p cairo_ft_font_face_create_for_ft_face (const(FT_Face) face, int load_flags); void cairo_font_face_destroy (cairo_font_face_p font_face); cairo_status_t cairo_font_face_status (cairo_font_face_p font_face); cairo_font_face_p cairo_get_font_face (cairo_p cr); void cairo_set_font_face (cairo_p cr, cairo_font_face_p font_face); void cairo_set_font_size (cairo_p cr, double size); void cairo_show_text (cairo_p cr, const(char) *utf8); // Toy API void cairo_text_extents (cairo_p cr, const(char) *utf8, cairo_text_extents_t *extents); appstream-generator-0.6.8/src/asgen/bindings/fontconfig.d000066400000000000000000000062371320016272000234700ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.fontconfig; extern(C): nothrow: @nogc: alias FcChar8 = char; alias FcBool = int; struct FcPattern {}; struct FcConfig {}; struct FcMatrix {}; struct FcCharSet {}; struct FcLangSet {}; struct FcRange {} struct FcStrList {}; struct FcStrSet {}; struct FcBlanks {}; immutable char *FC_LANG = "lang"; // String RFC 3066 langs immutable char *FC_STYLE = "style"; // String immutable char *FC_FULLNAME = "fullname"; // String struct FcFontSet { int nfont; int sfont; FcPattern **fonts; }; enum FcType { Unknown = -1, Void, Integer, Double, String, Bool, Matrix, CharSet, FTFace, LangSet }; struct FcValue { FcType type; union { const FcChar8 *s; int i; FcBool b; double d; const FcMatrix *m; const FcCharSet *c; void *f; const FcLangSet *l; const FcRange *r; }; }; enum FcSetName { System = 0, Application = 1 }; enum FcResult { Match, NoMatch, TypeMismatch, NoId, OutOfMemory }; FcBool FcInit (); FcConfig *FcConfigCreate (); void FcConfigDestroy (FcConfig *config); void FcConfigAppFontClear (FcConfig *config); bool FcConfigSetCurrent (FcConfig *config); bool FcConfigAppFontAddFile (FcConfig *config, const char *file); FcFontSet *FcConfigGetFonts (FcConfig *config, FcSetName set); FcPattern *FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count); void FcPatternDestroy (FcPattern *p); FcResult FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v); FcResult FcPatternGetLangSet (const FcPattern *p, const char *object, int n, FcLangSet **ls); FcResult FcPatternGetString (const FcPattern *p, const char *object, int n, FcChar8 ** s); FcStrList *FcStrListCreate (FcStrSet *set); void FcStrListFirst (FcStrList *list); char *FcStrListNext (FcStrList *list); void FcStrListDone (FcStrList *list); FcStrSet *FcLangSetGetLangs (const FcLangSet *ls); void FcStrSetDestroy (FcStrSet *set); appstream-generator-0.6.8/src/asgen/bindings/freetype.d000066400000000000000000000041371320016272000231540ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.freetype; public import asgen.bindings.freetypeTypes; extern(C): nothrow: @nogc: FT_Error FT_Init_FreeType (FT_Library *alibrary); FT_Error FT_Done_Library (FT_Library library); FT_Error FT_New_Face (FT_Library library, const(char) *filepathname, FT_Long face_index, FT_Face *aface); FT_Error FT_New_Memory_Face (FT_Library library, const FT_Byte *file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface); FT_Error FT_Done_Face (FT_Face face); FT_Error FT_Get_BDF_Charset_ID (FT_Face face, const char* *acharset_encoding, const char* *acharset_registry); FT_UInt FT_Get_Char_Index (FT_Face face, FT_ULong charcode); FT_ULong FT_Get_First_Char (FT_Face face, FT_UInt *agindex); FT_ULong FT_Get_Next_Char (FT_Face face, FT_ULong char_code, FT_UInt *agindex); FT_Error FT_Select_Charmap (FT_Face face, FT_Encoding encoding); FT_Error FT_Set_Charmap (FT_Face face, FT_CharMap charmap); appstream-generator-0.6.8/src/asgen/bindings/freetypeTypes.d000066400000000000000000001750171320016272000242070ustar00rootroot00000000000000/* Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ module asgen.bindings.freetypeTypes; import core.stdc.config : c_long, c_ulong; extern(C): nothrow: @nogc: // config/ftconfig.h alias FT_Int16 = short; alias FT_UInt16 = ushort; alias FT_Int32 = int; alias FT_UInt32 = uint; alias FT_Fast = int; alias FT_UFast = uint; alias FT_Int64 = long; alias FT_Uint64 = ulong; // fttypes.h alias FT_Bool = ubyte; alias FT_FWord = short; alias FT_UFWord = ushort; alias FT_Char = char; alias FT_Byte = ubyte; alias FT_Bytes = FT_Byte*; alias FT_Tag = FT_UInt32; alias FT_String = char; alias FT_Short = short; alias FT_UShort = ushort; alias FT_Int = int; alias FT_UInt = uint; alias FT_Long = c_long; alias FT_ULong = c_ulong; alias FT_F2Dot14 = short; alias FT_F26Dot6 = c_long; alias FT_Fixed = c_long; alias FT_Error = int; alias FT_Pointer = void*; alias FT_Offset = size_t; alias FT_PtrDist = ptrdiff_t; struct FT_UnitVector { FT_F2Dot14 x; FT_F2Dot14 y; } struct FT_Matrix { FT_Fixed xx, xy; FT_Fixed yx, yy; } struct FT_Data { const( FT_Byte )* pointer; FT_Int length; } extern( C ) nothrow alias FT_Generic_Finalizer = void function( void* ); struct FT_Generic { void* data; FT_Generic_Finalizer finalizer; } FT_Tag FT_MAKE_TAG( char x1, char x2, char x3, char x4 ) { return cast( FT_UInt32)(( x1 << 24 ) | ( x2 << 16 ) | ( x3 << 8 ) | x4 ); } alias FT_ListNode = FT_ListNodeRec*; alias FT_List = FT_ListRec*; struct FT_ListNodeRec { FT_ListNode prev; FT_ListNode next; void* data; } struct FT_ListRec { FT_ListNode head; FT_ListNode tail; } // freetype.h struct FT_Glyph_Metrics { FT_Pos width; FT_Pos height; FT_Pos horiBearingX; FT_Pos horiBearingY; FT_Pos horiAdvance; FT_Pos vertBearingX; FT_Pos vertBearingY; FT_Pos vertAdvance; } struct FT_Bitmap_Size { FT_Short height; FT_Short width; FT_Pos size; FT_Pos x_ppem; FT_Pos y_ppem; } struct FT_LibraryRec; struct FT_ModuleRec; struct FT_DriverRec; struct FT_RendererRec; alias FT_Library = FT_LibraryRec*; alias FT_Module = FT_ModuleRec*; alias FT_Driver = FT_DriverRec*; alias FT_Renderer = FT_RendererRec*; alias FT_Face = FT_FaceRec*; alias FT_Size = FT_SizeRec*; alias FT_GlyphSlot = FT_GlyphSlotRec*; alias FT_CharMap = FT_CharMapRec*; alias FT_ENC_TAG = FT_MAKE_TAG; alias FT_Encoding = FT_Tag; enum : FT_Tag { FT_ENCODING_NONE = 0, FT_ENCODING_MS_SYMBOL = FT_MAKE_TAG( 's','y','m','b' ), FT_ENCODING_UNICODE = FT_MAKE_TAG( 'u','n','i','c' ), FT_ENCODING_SJIS = FT_MAKE_TAG( 's','j','i','s' ), FT_ENCODING_GB2312 = FT_MAKE_TAG( 'g','b',' ',' ' ), FT_ENCODING_BIG5 = FT_MAKE_TAG('b','i','g','5' ), FT_ENCODING_WANSUNG = FT_MAKE_TAG( 'w','a','n','s' ), FT_ENCODING_JOHAB = FT_MAKE_TAG( 'j','o','h','a' ), FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS, FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312, FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5, FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG, FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB, FT_ENCODING_ADOBE_STANDARD = FT_MAKE_TAG( 'A','D','O','B' ), FT_ENCODING_ADOBE_EXPERT = FT_MAKE_TAG( 'A','D','B','E' ), FT_ENCODING_ADOBE_CUSTOM = FT_MAKE_TAG( 'A','D','B','C' ), FT_ENCODING_ADOBE_LATIN_1 = FT_MAKE_TAG( 'l','a','t','1' ), FT_ENCODING_OLD_LATIN_2 = FT_MAKE_TAG( 'l','a','t','2' ), FT_ENCODING_APPLE_ROMAN = FT_MAKE_TAG( 'a','r','m','n' ), } struct FT_CharMapRec { FT_Face face; FT_Encoding encoding; FT_UShort platform_id; FT_UShort encoding_id; } struct FT_Face_InternalRec; alias FT_Face_Internal = FT_Face_InternalRec*; struct FT_FaceRec { FT_Long num_faces; FT_Long face_index; FT_Long face_flags; FT_Long style_flags; FT_Long num_glyphs; FT_String* family_name; FT_String* style_name; FT_Int num_fixed_sizes; FT_Bitmap_Size* available_sizes; FT_Int num_charmaps; FT_CharMap* charmaps; FT_Generic generic; FT_BBox bbox; FT_UShort units_per_EM; FT_Short ascender; FT_Short descender; FT_Short height; FT_Short max_advance_width; FT_Short max_advance_height; FT_Short underline_position; FT_Short underline_thickness; FT_GlyphSlot glyph; FT_Size size; FT_CharMap charmap; FT_Driver driver; FT_Memory memory; FT_Stream stream; FT_ListRec sizes_list; FT_Generic autohint; void* extensions; FT_Face_Internal internal; } enum : uint { FT_FACE_FLAG_SCALABLE = 1 << 0, FT_FACE_FLAG_FIXED_SIZES = 1 << 1, FT_FACE_FLAG_FIXED_WIDTH = 1 << 2, FT_FACE_FLAG_SFNT = 1 << 3, FT_FACE_FLAG_HORIZONTAL = 1 << 4, FT_FACE_FLAG_VERTICAL = 1 << 5, FT_FACE_FLAG_KERNING = 1 << 6, FT_FACE_FLAG_FAST_GLYPHS = 1 << 7, FT_FACE_FLAG_MULTIPLE_MASTERS = 1 << 8, FT_FACE_FLAG_GLYPH_NAMES = 1 << 9, FT_FACE_FLAG_EXTERNAL_STREAM = 1 << 10, FT_FACE_FLAG_HINTER = 1 << 11, FT_FACE_FLAG_CID_KEYED = 1 << 12, FT_FACE_FLAG_TRICKY = 1 << 13, FT_FACE_FLAG_COLOR = 1 << 14, } @nogc nothrow { bool FT_HAS_HORIZONTAL( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_HORIZONTAL ) == 0; } bool FT_HAS_VERTICAL( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_VERTICAL ) == 0; } bool FT_HAS_KERNING( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_KERNING ) == 0; } bool FT_IS_SCALABLE( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_SCALABLE ) == 0; } bool FT_IS_SFNT( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_SFNT ) == 0; } bool FT_IS_FIXED_WIDTH( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_FIXED_WIDTH ) == 0; } bool FT_HAS_FIXED_SIZES( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_FIXED_SIZES ) == 0; } bool FT_HAS_FAST_GLYPHS( FT_FaceRec* face ) { return false; } bool FT_HAS_GLYPH_NAMES( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_GLYPH_NAMES ) == 0; } bool FT_HAS_MULTIPLE_MASTERS( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) == 0; } bool FT_IS_CID_KEYED( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_CID_KEYED ) == 0; } bool FT_IS_TRICKY( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_TRICKY ) == 0; } bool FT_HAS_COLOR( FT_FaceRec* face ) { return ( face.face_flags & FT_FACE_FLAG_COLOR ) == 0; } } enum { FT_STYLE_FLAG_ITALIC = 1 << 0, FT_STYLE_FLAG_BOLD = 1 << 1, } struct FT_Size_InternalRec; alias FT_Size_Internal = FT_Size_InternalRec*; struct FT_Size_Metrics { FT_UShort x_ppem; FT_UShort y_ppem; FT_Fixed x_scale; FT_Fixed y_scale; FT_Pos ascender; FT_Pos descender; FT_Pos height; FT_Pos max_advance; } struct FT_SizeRec { FT_Face face; FT_Generic generic; FT_Size_Metrics metrics; FT_Size_Internal internal; } struct FT_SubGlyphRec; struct FT_Slot_InternalRec; alias FT_SubGlyph = FT_SubGlyphRec*; alias FT_Slot_Internal = FT_Slot_InternalRec*; struct FT_GlyphSlotRec { FT_Library library; FT_Face face; FT_GlyphSlot next; FT_UInt reserved; FT_Generic generic; FT_Glyph_Metrics metrics; FT_Fixed linearHoriAdvance; FT_Fixed linearVertAdvance; FT_Vector advance; FT_Glyph_Format format; FT_Bitmap bitmap; FT_Int bitmap_left; FT_Int bitmap_top; FT_Outline outline; FT_UInt num_subglyphs; FT_SubGlyph subglyphs; void* control_data; c_long control_len; FT_Pos lsb_delta; FT_Pos rsb_delta; void* other; FT_Slot_Internal internal; } enum : uint { FT_OPEN_MEMORY = 0x1, FT_OPEN_STREAM = 0x2, FT_OPEN_DRIVER = 0x4, FT_OPEN_PATHNAME = 0x8, FT_OPEN_PARAMS = 0x10, } struct FT_Parameter { FT_ULong tag; FT_Pointer data; } struct FT_Open_Args { FT_UInt flags; const( FT_Byte )* memory_base; FT_Long memory_size; FT_String* pathname; FT_Stream stream; FT_Module driver; FT_Int num_params; FT_Parameter* params; } alias FT_Size_Request_Type = int; enum { FT_SIZE_REQUEST_TYPE_NOMINAL, FT_SIZE_REQUEST_TYPE_REAL_DIM, FT_SIZE_REQUEST_TYPE_BBOX, FT_SIZE_REQUEST_TYPE_CELL, FT_SIZE_REQUEST_TYPE_SCALES, FT_SIZE_REQUEST_TYPE_MAX } struct FT_Size_RequestRec { FT_Size_Request_Type type; FT_Long width; FT_Long height; FT_UInt horiResolution; FT_UInt vertResolution; } alias FT_Size_Request = FT_Size_RequestRec*; enum : uint { FT_LOAD_DEFAULT = 0x0, FT_LOAD_NO_SCALE = 1 << 0, FT_LOAD_NO_HINTING = 1 << 1, FT_LOAD_RENDER = 1 << 2, FT_LOAD_NO_BITMAP = 1 << 3, FT_LOAD_VERTICAL_LAYOUT = 1 << 4, FT_LOAD_FORCE_AUTOHINT = 1 << 5, FT_LOAD_CROP_BITMAP = 1 << 6, FT_LOAD_PEDANTIC = 1 << 7, FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = 1 << 9, FT_LOAD_NO_RECURSE = 1 << 10, FT_LOAD_IGNORE_TRANSFORM = 1 << 11, FT_LOAD_MONOCHROME = 1 << 12, FT_LOAD_LINEAR_DESIGN = 1 << 13, FT_LOAD_NO_AUTOHINT = 1 << 15, FT_LOAD_COLOR = 1 << 20, FT_LOAD_COMPUTE_METRICS = 1 << 21, } enum { FT_LOAD_TARGET_NORMAL = ( FT_RENDER_MODE_NORMAL & 15 ) << 16, FT_LOAD_TARGET_LIGHT = ( FT_RENDER_MODE_LIGHT & 15 ) << 16, FT_LOAD_TARGET_MONO = ( FT_RENDER_MODE_MONO & 15 ) << 16, FT_LOAD_TARGET_LCD = ( FT_RENDER_MODE_LCD & 15 ) << 16, FT_LOAD_TARGET_LCD_V = ( FT_RENDER_MODE_LCD_V & 15 ) << 16, } @nogc FT_Render_Mode FT_LOAD_TARGET_MODE( uint x ) nothrow { return cast( FT_Render_Mode )(( x >> 16 ) & 15 ); } alias FT_Render_Mode = uint; enum { FT_RENDER_MODE_NORMAL = 0, FT_RENDER_MODE_LIGHT, FT_RENDER_MODE_MONO, FT_RENDER_MODE_LCD, FT_RENDER_MODE_LCD_V, FT_RENDER_MODE_MAX } enum FT_Kerning_Mode { FT_KERNING_DEFAULT = 0, FT_KERNING_UNFITTED, FT_KERNING_UNSCALED } enum { FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS = 1, FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES = 2, FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID = 4, FT_SUBGLYPH_FLAG_SCALE = 8, FT_SUBGLYPH_FLAG_XY_SCALE = 0x40, FT_SUBGLYPH_FLAG_2X2 = 0x80, FT_SUBGLYPH_FLAG_USE_MY_METRICS = 0x200, } enum { FT_FSTYPE_INSTALLABLE_EMBEDDING = 0x0000, FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING = 0x0002, FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING = 0x0004, FT_FSTYPE_EDITABLE_EMBEDDING = 0x0008, FT_FSTYPE_NO_SUBSETTING = 0x0100, FT_FSTYPE_BITMAP_EMBEDDING_ONLY = 0x0200, } enum { FREETYPE_MAJOR = 2, FREETYPE_MINOR = 6, FREETYPE_PATCH = 3, } // ftadvanc.h enum FT_ADVANCE_FLAG_FAST_ONLY = 0x20000000; // ftautoh.h enum { FT_AUTOHINTER_SCRIPT_NONE = 0, FT_AUTOHINTER_SCRIPT_LATIN = 1, FT_AUTOHINTER_SCRIPT_CJK = 2, FT_AUTOHINTER_SCRIPT_INDIC = 3, } struct FT_Prop_GlyphToScriptMap { FT_Face face; FT_UShort* map; } struct FT_Prop_IncreaseXHeight { FT_Face face; FT_UInt32 limit; } // ftbdf.h version( linux ) { alias BDF_PropertyType = int; enum { BDF_PROPERTY_TYPE_NONE = 0, BDF_PROPERTY_TYPE_ATOM = 1, BDF_PROPERTY_TYPE_INTEGER = 2, BDF_PROPERTY_TYPE_CARDINAL = 3 } alias BDF_Property = BDF_PropertyRec*; struct BDF_PropertyRec { BDF_PropertyType type; union u { char* atom; FT_Int32 integer; FT_UInt32 cardinal; } } } // ftcache.h alias FTC_FaceID = FT_Pointer; extern( C ) nothrow alias FTC_Face_Requester = FT_Error function( FTC_FaceID,FT_Library,FT_Pointer,FT_Face* ); struct FTC_ManagerRec; struct FTC_NodeRec; alias FTC_Manager = FTC_ManagerRec*; alias FTC_Node = FTC_NodeRec*; struct FTC_ScalerRec { FTC_FaceID face_id; FT_UInt width; FT_UInt height; FT_Int pixel; FT_UInt x_res; FT_UInt y_res; } alias FTC_Scaler = FTC_ScalerRec*; struct FTC_CMapCacheRec; alias FTC_CMapCache = FTC_CMapCacheRec*; struct FTC_ImageTypeRec { FTC_FaceID face_id; FT_UInt width; FT_UInt height; FT_Int32 flags; } alias FTC_ImageType = FTC_ImageTypeRec*; struct FTC_ImageCacheRec; alias FTC_ImageCache = FTC_ImageCacheRec*; alias FTC_SBit = FTC_SBitRec*; struct FTC_SBitRec { FT_Byte width; FT_Byte height; FT_Char left; FT_Char top; FT_Byte format; FT_Byte max_grays; FT_Short pitch; FT_Char xadvance; FT_Char yadvance; FT_Byte* buffer; } struct FTC_SBitCacheRec; alias FTC_SBitCache = FTC_SBitCacheRec*; // ftcffdrv.h enum { FT_CFF_HINTING_FREETYPE = 0, FT_CFF_HINTING_ADOBE = 1, } // fterrdef.h enum { FT_Err_Ok = 0x00, FT_Err_Cannot_Open_Resource = 0x01, FT_Err_Unknown_File_Format = 0x02, FT_Err_Invalid_File_Format = 0x03, FT_Err_Invalid_Version = 0x04, FT_Err_Lower_Module_Version = 0x05, FT_Err_Invalid_Argument = 0x06, FT_Err_Unimplemented_Feature = 0x07, FT_Err_Invalid_Table = 0x08, FT_Err_Invalid_Offset = 0x09, FT_Err_Array_Too_Large = 0x0A, FT_Err_Missing_Module = 0x0B, FT_Err_Missing_Property = 0x0C, FT_Err_Invalid_Glyph_Index = 0x10, FT_Err_Invalid_Character_Code = 0x11, FT_Err_Invalid_Glyph_Format = 0x12, FT_Err_Cannot_Render_Glyph = 0x13, FT_Err_Invalid_Outline = 0x14, FT_Err_Invalid_Composite = 0x15, FT_Err_Too_Many_Hints = 0x16, FT_Err_Invalid_Pixel_Size = 0x17, FT_Err_Invalid_Handle = 0x20, FT_Err_Invalid_Library_Handle = 0x21, FT_Err_Invalid_Driver_Handle = 0x22, FT_Err_Invalid_Face_Handle = 0x23, FT_Err_Invalid_Size_Handle = 0x24, FT_Err_Invalid_Slot_Handle = 0x25, FT_Err_Invalid_CharMap_Handle = 0x26, FT_Err_Invalid_Cache_Handle = 0x27, FT_Err_Invalid_Stream_Handle = 0x28, FT_Err_Too_Many_Drivers = 0x30, FT_Err_Too_Many_Extensions = 0x31, FT_Err_Out_Of_Memory = 0x40, FT_Err_Unlisted_Object = 0x41, FT_Err_Cannot_Open_Stream = 0x51, FT_Err_Invalid_Stream_Seek = 0x52, FT_Err_Invalid_Stream_Skip = 0x53, FT_Err_Invalid_Stream_Read = 0x54, FT_Err_Invalid_Stream_Operation = 0x55, FT_Err_Invalid_Frame_Operation = 0x56, FT_Err_Nested_Frame_Access = 0x57, FT_Err_Invalid_Frame_Read = 0x58, FT_Err_Raster_Uninitialized = 0x60, FT_Err_Raster_Corrupted = 0x61, FT_Err_Raster_Overflow = 0x62, FT_Err_Raster_Negative_Height = 0x63, FT_Err_Too_Many_Caches = 0x70, FT_Err_Invalid_Opcode = 0x80, FT_Err_Too_Few_Arguments = 0x81, FT_Err_Stack_Overflow = 0x82, FT_Err_Code_Overflow = 0x83, FT_Err_Bad_Argument = 0x84, FT_Err_Divide_By_Zero = 0x85, FT_Err_Invalid_Reference = 0x86, FT_Err_Debug_OpCode = 0x87, FT_Err_ENDF_In_Exec_Stream = 0x88, FT_Err_Nested_DEFS = 0x89, FT_Err_Invalid_CodeRange = 0x8A, FT_Err_Execution_Too_Long = 0x8B, FT_Err_Too_Many_Function_Defs = 0x8C, FT_Err_Too_Many_Instruction_Defs = 0x8D, FT_Err_Table_Missing = 0x8E, FT_Err_Horiz_Header_Missing = 0x8F, FT_Err_Locations_Missing = 0x90, FT_Err_Name_Table_Missing = 0x91, FT_Err_CMap_Table_Missing = 0x92, FT_Err_Hmtx_Table_Missing = 0x93, FT_Err_Post_Table_Missing = 0x94, FT_Err_Invalid_Horiz_Metrics = 0x95, FT_Err_Invalid_CharMap_Format = 0x96, FT_Err_Invalid_PPem = 0x97, FT_Err_Invalid_Vert_Metrics = 0x98, FT_Err_Could_Not_Find_Context = 0x99, FT_Err_Invalid_Post_Table_Format = 0x9A, FT_Err_Invalid_Post_Table = 0x9B, FT_Err_Syntax_Error = 0xA0, FT_Err_Stack_Underflow = 0xA1, FT_Err_Ignore = 0xA2, FT_Err_No_Unicode_Glyph_Name = 0xA3, FT_Err_Glyph_Too_Big = 0xA4, FT_Err_Missing_Startfont_Field = 0xB0, FT_Err_Missing_Font_Field = 0xB1, FT_Err_Missing_Size_Field = 0xB2, FT_Err_Missing_Fontboundingbox_Field = 0xB3, FT_Err_Missing_Chars_Field = 0xB4, FT_Err_Missing_Startchar_Field = 0xB5, FT_Err_Missing_Encoding_Field = 0xB6, FT_Err_Missing_Bbx_Field = 0xB7, FT_Err_Bbx_Too_Big = 0xB8, FT_Err_Corrupted_Font_Header = 0xB9, FT_Err_Corrupted_Font_Glyphs = 0xBA, FT_Err_Max, } // ftgasp.h enum { FT_GASP_NO_TABLE = -1, FT_GASP_DO_GRIDFIT = 0x01, FT_GASP_DO_GRAY = 0x02, FT_GASP_SYMMETRIC_SMOOTHING = 0x08, FT_GASP_SYMMETRIC_GRIDFIT = 0x10 } // ftglyph.h alias FT_Glyph = FT_GlyphRec*; struct FT_GlyphRec { FT_Library library; FT_Glyph_Class* clazz; FT_Glyph_Format format; FT_Vector advance; } alias FT_BitmapGlyph = FT_BitmapGlyphRec*; struct FT_BitmapGlyphRec { FT_GlyphRec root; FT_Int left; FT_Int top; FT_Bitmap bitmap; } alias FT_OutlineGlyph = FT_OutlineGlyphRec*; struct FT_OutlineGlyphRec { FT_GlyphRec root; FT_Outline outline; } alias FT_Glyph_BBox_Mode = int; enum { FT_GLYPH_BBOX_UNSCALED = 0, FT_GLYPH_BBOX_SUBPIXELS = 0, FT_GLYPH_BBOX_GRIDFIT = 1, FT_GLYPH_BBOX_TRUNCATE = 2, FT_GLYPH_BBOX_PIXELS = 3 } // ftgxval.h enum { FT_VALIDATE_feat_INDEX = 0, FT_VALIDATE_mort_INDEX = 1, FT_VALIDATE_morx_INDEX = 2, FT_VALIDATE_bsln_INDEX = 3, FT_VALIDATE_just_INDEX = 4, FT_VALIDATE_kern_INDEX = 5, FT_VALIDATE_opbd_INDEX = 6, FT_VALIDATE_trak_INDEX = 7, FT_VALIDATE_prop_INDEX = 8, FT_VALIDATE_lcar_INDEX = 9, FT_VALIDATE_GX_LAST_INDEX = FT_VALIDATE_lcar_INDEX, FT_VALIDATE_GX_LENGTH = FT_VALIDATE_GX_LAST_INDEX + 1, FT_VALIDATE_GX_START = 0x4000, FT_VALIDATE_feat = FT_VALIDATE_GX_START << FT_VALIDATE_feat_INDEX, FT_VALIDATE_mort = FT_VALIDATE_GX_START << FT_VALIDATE_mort_INDEX, FT_VALIDATE_morx = FT_VALIDATE_GX_START << FT_VALIDATE_morx_INDEX, FT_VALIDATE_bsln = FT_VALIDATE_GX_START << FT_VALIDATE_bsln_INDEX, FT_VALIDATE_just = FT_VALIDATE_GX_START << FT_VALIDATE_just_INDEX, FT_VALIDATE_kern = FT_VALIDATE_GX_START << FT_VALIDATE_kern_INDEX, FT_VALIDATE_opbd = FT_VALIDATE_GX_START << FT_VALIDATE_opbd_INDEX, FT_VALIDATE_trak = FT_VALIDATE_GX_START << FT_VALIDATE_trak_INDEX, FT_VALIDATE_prop = FT_VALIDATE_GX_START << FT_VALIDATE_prop_INDEX, FT_VALIDATE_lcar = FT_VALIDATE_GX_START << FT_VALIDATE_lcar_INDEX, FT_VALIDATE_GX = ( FT_VALIDATE_feat | FT_VALIDATE_mort | FT_VALIDATE_morx | FT_VALIDATE_bsln | FT_VALIDATE_just | FT_VALIDATE_kern | FT_VALIDATE_opbd | FT_VALIDATE_trak | FT_VALIDATE_prop | FT_VALIDATE_lcar ), FT_VALIDATE_MS = FT_VALIDATE_GX_START << 0, FT_VALIDATE_APPLE = FT_VALIDATE_GX_START << 1, FT_VALIDATE_CKERN = FT_VALIDATE_MS | FT_VALIDATE_APPLE, } // ftimage.h alias FT_Pos = c_long; struct FT_Vector { FT_Pos x; FT_Pos y; } struct FT_BBox { FT_Pos xMin, yMin; FT_Pos xMax, yMax; } alias FT_Pixel_Mode = int; enum { FT_PIXEL_MODE_NONE = 0, FT_PIXEL_MODE_MONO, FT_PIXEL_MODE_GRAY, FT_PIXEL_MODE_GRAY2, FT_PIXEL_MODE_GRAY4, FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_LCD_V, FT_PIXEL_MODE_MAX } struct FT_Bitmap { uint rows; uint width; int pitch; ubyte* buffer; ushort num_grays; ubyte pixel_mode; ubyte palette_mode; void* palette; } struct FT_Outline { short n_contours; short n_points; FT_Vector* points; byte* tags; short* contours; int flags; } enum FT_OUTLINE_CONTOURS_MAX = short.max; enum FT_OUTLINE_POINTS_MAX = short.max; enum : uint { FT_OUTLINE_NONE = 0x0, FT_OUTLINE_OWNER = 0x1, FT_OUTLINE_EVEN_ODD_FILL = 0x2, FT_OUTLINE_REVERSE_FILL = 0x4, FT_OUTLINE_IGNORE_DROPOUTS = 0x8, FT_OUTLINE_HIGH_PRECISION = 0x100, FT_OUTLINE_SINGLE_PASS = 0x200, } enum { FT_CURVE_TAG_ON = 1, FT_CURVE_TAG_CONIC = 0, FT_CURVE_TAG_CUBIC = 2, FT_CURVE_TAG_TOUCH_X = 8, FT_CURVE_TAG_TOUCH_Y = 16, FT_CURVE_TAG_TOUCH_BOTH = FT_CURVE_TAG_TOUCH_X | FT_CURVE_TAG_TOUCH_Y, } extern( C ) nothrow { alias FT_Outline_MoveToFunc = int function( const( FT_Vector )*, void* ); alias FT_Outline_LineToFunc = int function( const( FT_Vector )*, void* ); alias FT_Outline_ConicToFunc = int function( const( FT_Vector )*, const( FT_Vector )*, void* ); alias FT_Outline_CubicToFunc = int function( const( FT_Vector )*, const( FT_Vector )*, const( FT_Vector )*, void* ); } struct FT_Outline_Funcs { FT_Outline_MoveToFunc move_to; FT_Outline_LineToFunc line_to; FT_Outline_ConicToFunc conic_to; FT_Outline_CubicToFunc cubic_to; int shift; FT_Pos delta; } alias FT_Glyph_Format = FT_Tag; enum : FT_Tag { FT_GLYPH_FORMAT_NONE = 0, FT_GLYPH_FORMAT_COMPOSITE = FT_MAKE_TAG( 'c','o','m','p' ), FT_GLYPH_FORMAT_BITMAP = FT_MAKE_TAG( 'b','i','t','s' ), FT_GLYPH_FORMAT_OUTLINE = FT_MAKE_TAG( 'o','u','t','l' ), FT_GLYPH_FORMAT_PLOTTER = FT_MAKE_TAG( 'p','l','o','t' ), } struct FT_RasterRec; alias FT_Raster = FT_RasterRec*; struct FT_Span { short x; ushort len; ubyte coverage; } extern( C ) nothrow alias FT_SpanFunc = void function( int, int, FT_Span*, void* ); enum { FT_RASTER_FLAG_DEFAULT = 0x0, FT_RASTER_FLAG_AA = 0x1, FT_RASTER_FLAG_DIRECT = 0x2, FT_RASTER_FLAG_CLIP = 0x4 } struct FT_Raster_Params { const( FT_Bitmap )* target; const( void )* source; int flags; FT_SpanFunc gray_spans; void* black_spans; void* bit_test; void* bit_set; void* user; FT_BBox clip_box; } extern( C ) nothrow { alias FT_Raster_NewFunc = int function( void*, FT_Raster* ); alias FT_Raster_DoneFunc = void function( FT_Raster ); alias FT_Raster_ResetFunc = void function( FT_Raster, ubyte*, uint ); alias FT_Raster_SetModeFunc = int function( FT_Raster, uint, void* ); alias FT_Raster_RenderFunc = int function( FT_Raster, FT_Raster_Params* ); } struct FT_Raster_Funcs { FT_Glyph_Format glyph_format; FT_Raster_NewFunc raster_new; FT_Raster_ResetFunc raster_reset; FT_Raster_SetModeFunc raster_set_mode; FT_Raster_RenderFunc raster_render; FT_Raster_DoneFunc raster_done; } // ftincrem.h struct FT_IncrementalRec; alias FT_Incremental = FT_IncrementalRec*; struct FT_Incremental_MetricsRec { FT_Long bearing_x; FT_Long bearing_y; FT_Long advance; } alias FT_Incremental_Metrics = FT_Incremental_MetricsRec*; extern( C ) nothrow { alias FT_Incremental_GetGlyphDataFunc = FT_Error function( FT_Incremental, FT_UInt, FT_Data* ); alias FT_Incremental_FreeGlyphDataFunc = void function( FT_Incremental, FT_Data* ); alias FT_Incremental_GetGlyphMetricsFunc = FT_Error function( FT_Incremental, FT_UInt, FT_Bool, FT_Incremental_MetricsRec* ); } struct FT_Incremental_FuncsRec { FT_Incremental_GetGlyphDataFunc get_glyph_data; FT_Incremental_FreeGlyphDataFunc free_glyph_data; FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics; } struct FT_Incremental_InterfaceRec { FT_Incremental_FuncsRec* funcs; FT_Incremental object; } enum FT_PARAM_TAG_INCREMENTAL = FT_MAKE_TAG( 'i','n','c','r' ); alias FT_Incremental_Interface = FT_Incremental_InterfaceRec*; // ftlcdfil.h alias FT_LcdFilter = int; enum { FT_LCD_FILTER_NONE = 0, FT_LCD_FILTER_DEFAULT = 1, FT_LCD_FILTER_LIGHT = 2, FT_LCD_FILTER_LEGACY1 = 3, FT_LCD_FILTER_LEGACY = 16, FT_LCD_FILTER_MAX } // ftlist.h extern( C ) nothrow { alias FT_List_Iterator = FT_Error function( FT_ListNode, void* ); alias FT_List_Destructor = void function( FT_Memory, void*, void* ); } // ftmm.h struct FT_MM_Axis { FT_String* name; FT_Long minimum; FT_Long maximum; } struct FT_Multi_Master { FT_UInt num_axis; FT_UInt num_designs; FT_MM_Axis[4] axis; } struct FT_Var_Axis { FT_String* name; FT_Fixed minimum; FT_Fixed def; FT_Fixed maximum; FT_ULong tag; FT_UInt strid; } struct FT_Var_Named_Style { FT_Fixed* coords; FT_UInt strid; } struct FT_MM_Var { FT_UInt num_axis; FT_UInt num_designs; FT_UInt num_namedstyles; FT_Var_Axis* axis; FT_Var_Named_Style* namedstyle; } // ftmodapi.h enum { FT_MODULE_FONT_DRIVER = 1, FT_MODULE_RENDERER = 2, FT_MODULE_HINTER = 4, FT_MODULE_STYLER = 8, FT_MODULE_DRIVER_SCALABLE = 0x100, FT_MODULE_DRIVER_NO_OUTLINES= 0x200, FT_MODULE_DRIVER_HAS_HINTER = 0x400, FT_MODULE_DRIVER_HINTS_LIGHTLY = 0x800, } alias FT_Module_Interface = FT_Pointer; extern( C ) nothrow { alias FT_Module_Constructor = FT_Error function( FT_Module ); alias FT_Module_Destructor = void function( FT_Module ); alias FT_Module_Requester = FT_Module_Interface function( FT_Module, const( char )* ); } struct FT_Module_Class { FT_ULong module_flags; FT_Long module_size; FT_String* module_name; FT_Fixed module_version; FT_Fixed module_requires; void* module_interface; FT_Module_Constructor module_init; FT_Module_Destructor module_done; FT_Module_Requester get_interface; } extern( C ) nothrow alias FT_DebugHook_Func = void function( void* ); alias FT_TrueTypeEngineType = int; enum { FT_TRUETYPE_ENGINE_TYPE_NONE = 0, FT_TRUETYPE_ENGINE_TYPE_UNPATENTED, FT_TRUETYPE_ENGINE_TYPE_PATENTED } // ftmoderr.h enum { FT_Mod_Err_Base = 0x000, FT_Mod_Err_Autofit = 0x100, FT_Mod_Err_BDF = 0x200, FT_Mod_Err_Bzip2 = 0x300, FT_Mod_Err_Cache = 0x400, FT_Mod_Err_CFF = 0x500, FT_Mod_Err_CID = 0x600, FT_Mod_Err_Gzip = 0x700, FT_Mod_Err_LZW = 0x800, FT_Mod_Err_OTvalid = 0x900, FT_Mod_Err_PCF = 0xA00, FT_Mod_Err_PFR = 0xB00, FT_Mod_Err_PSaux = 0xC00, FT_Mod_Err_PShinter = 0xD00, FT_Mod_Err_PSnames = 0xE00, FT_Mod_Err_Raster = 0xF00, FT_Mod_Err_SFNT = 0x1000, FT_Mod_Err_Smooth = 0x1100, FT_Mod_Err_TrueType = 0x1200, FT_Mod_Err_Type1 = 0x1300, FT_Mod_Err_Type42 = 0x1400, FT_Mod_Err_Winfonts = 0x1500, FT_Mod_Err_GXvalid = 0x1600, FT_Mod_Err_Max, } // ftotval.h enum { FT_VALIDATE_BASE = 0x0100, FT_VALIDATE_GDEF = 0x0200, FT_VALIDATE_GPOS = 0x0400, FT_VALIDATE_GSUB = 0x0800, FT_VALIDATE_JSTF = 0x1000, FT_VALIDATE_MATH = 0x2000, FT_VALIDATE_OT = FT_VALIDATE_BASE | FT_VALIDATE_GDEF | FT_VALIDATE_GPOS | FT_VALIDATE_GSUB | FT_VALIDATE_JSTF | FT_VALIDATE_MATH, } // ftoutln alias FT_Orientation = int; enum { FT_ORIENTATION_TRUETYPE = 0, FT_ORIENTATION_POSTSCRIPT = 1, FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE, FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT } // ftrender.h extern( C ) nothrow { alias FT_Glyph_InitFunc = FT_Error function( FT_Glyph, FT_GlyphSlot ); alias FT_Glyph_DoneFunc = void function( FT_Glyph ); alias FT_Glyph_TransformFunc = void function( FT_Glyph, const( FT_Matrix )* matrix, const( FT_Vector )* ); alias FT_Glyph_GetBBoxFunc = void function( FT_Glyph, FT_BBox* ); alias FT_Glyph_CopyFunc = FT_Error function( FT_Glyph, FT_Glyph ); alias FT_Glyph_PrepareFunc = FT_Error function( FT_Glyph, FT_GlyphSlot ); } struct FT_Glyph_Class { // typedef'd in ftglyph.h FT_Long glyph_size; FT_Glyph_Format glyph_format; FT_Glyph_InitFunc glyph_init; FT_Glyph_DoneFunc glyph_done; FT_Glyph_CopyFunc glyph_copy; FT_Glyph_TransformFunc glyph_transform; FT_Glyph_GetBBoxFunc glyph_bbox; FT_Glyph_PrepareFunc glyph_prepare; } extern( C ) nothrow { alias FT_Renderer_RenderFunc = FT_Error function( FT_Renderer, FT_GlyphSlot, FT_UInt, const( FT_Vector )* ); alias FT_Renderer_TransformFunc = FT_Error function( FT_Renderer, FT_GlyphSlot, const( FT_Matrix )*, const( FT_Vector )* ); alias FT_Renderer_GetCBoxFunc = void function( FT_Renderer, FT_GlyphSlot, FT_BBox* ); alias FT_Renderer_SetModeFunc = FT_Error function( FT_Renderer, FT_ULong, FT_Pointer ); } struct FT_Renderer_Class { FT_Module_Class root; FT_Glyph_Format glyph_format; FT_Renderer_RenderFunc render_glyph; FT_Renderer_TransformFunc transform_glyph; FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_SetModeFunc set_mode; FT_Raster_Funcs* raster_class; } // ftsnames.h struct FT_SfntName { FT_UShort platform_id; FT_UShort encoding_id; FT_UShort language_id; FT_UShort name_id; FT_Byte* string; FT_UInt string_len; } enum FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY = FT_MAKE_TAG( 'i','g','p','f' ); enum FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY = FT_MAKE_TAG( 'i','g','p','s' ); // ftstroke.h struct FT_StrokerRec; alias FT_Stroker = FT_StrokerRec*; alias FT_Stroker_LineJoin = int; enum { FT_STROKER_LINEJOIN_ROUND = 0, FT_STROKER_LINEJOIN_BEVEL, FT_STROKER_LINEJOIN_MITER } alias FT_Stroker_LineCap = int; enum { FT_STROKER_LINECAP_BUTT = 0, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINECAP_SQUARE } alias FT_StrokerBorder = int; enum { FT_STROKER_BORDER_LEFT = 0, FT_STROKER_BORDER_RIGHT } // ftsystem.h alias FT_Memory = FT_MemoryRec*; extern( C ) nothrow { alias FT_Alloc_Func = void* function( FT_Memory, c_long ); alias FT_Free_Func = void function( FT_Memory, void* ); alias FT_Realloc_Func = void* function( FT_Memory, c_long, c_long, void* ); } struct FT_MemoryRec { void* user; FT_Alloc_Func alloc; FT_Free_Func free; FT_Realloc_Func realloc; } alias FT_Stream = FT_StreamRec*; union FT_StreamDesc { int value; void* pointer; } extern( C ) nothrow { alias FT_Stream_IoFunc = c_ulong function( FT_Stream, c_ulong, ubyte*, c_ulong ); alias FT_Stream_CloseFunc = void function( FT_Stream ); } struct FT_StreamRec { ubyte* base; c_ulong size; c_ulong pos; FT_StreamDesc descriptor; FT_StreamDesc pathname; FT_Stream_IoFunc read; FT_Stream_CloseFunc close; FT_Memory memory; ubyte* cursor; ubyte* limit; } // fttrigon.h alias FT_Angle = FT_Fixed; enum { FT_ANGLE_PI = 180 << 16, FT_ANGLE_2PI = FT_ANGLE_PI * 2, FT_ANGLE_PI2 = FT_ANGLE_PI / 2, FT_ANGLE_PI4 = FT_ANGLE_PI / 4 } // ftttdrv.h enum TT_INTERPRETER_VERSION_35 = 35; enum TT_INTERPRETER_VERSION_38 = 38; // ftwinfnt.h enum { FT_WinFNT_ID_CP1252 = 0, FT_WinFNT_ID_DEFAULT = 1, FT_WinFNT_ID_SYMBOL = 2, FT_WinFNT_ID_MAC = 77, FT_WinFNT_ID_CP932 = 128, FT_WinFNT_ID_CP949 = 129, FT_WinFNT_ID_CP1361 = 130, FT_WinFNT_ID_CP936 = 134, FT_WinFNT_ID_CP950 = 136, FT_WinFNT_ID_CP1253 = 161, FT_WinFNT_ID_CP1254 = 162, FT_WinFNT_ID_CP1258 = 163, FT_WinFNT_ID_CP1255 = 177, FT_WinFNT_ID_CP1256 = 178, FT_WinFNT_ID_CP1257 = 186, FT_WinFNT_ID_CP1251 = 204, FT_WinFNT_ID_CP874 = 222, FT_WinFNT_ID_CP1250 = 238, FT_WinFNT_ID_OEM = 255, } struct FT_WinFNT_HeaderRec { FT_UShort _version; FT_ULong file_size; FT_Byte[60] copyright; FT_UShort file_type; FT_UShort nominal_point_size; FT_UShort vertical_resolution; FT_UShort horizontal_resolution; FT_UShort ascent; FT_UShort internal_leading; FT_UShort external_leading; FT_Byte italic; FT_Byte underline; FT_Byte strike_out; FT_UShort weight; FT_Byte charset; FT_UShort pixel_width; FT_UShort pixel_height; FT_Byte pitch_and_family; FT_UShort avg_width; FT_UShort max_width; FT_Byte first_char; FT_Byte last_char; FT_Byte default_char; FT_Byte break_char; FT_UShort bytes_per_row; FT_ULong device_offset; FT_ULong face_name_offset; FT_ULong bits_pointer; FT_ULong bits_offset; FT_Byte reserved; FT_ULong flags; FT_UShort A_space; FT_UShort B_space; FT_UShort C_space; FT_UShort color_table_offset; FT_ULong[4] reserved1; } alias FT_WinFNT_Header = FT_WinFNT_HeaderRec*; // t1tables.h struct PS_FontInfoRec { FT_String* _version; FT_String* notice; FT_String* full_name; FT_String* family_name; FT_String* weight; FT_Long italic_angle; FT_Bool is_fixed_pitch; FT_Short underline_position; FT_UShort underline_thickness; } alias PS_FontInfo = PS_FontInfoRec*; struct PS_PrivateRec { FT_Int unique_id; FT_Int lenIV; FT_Byte num_blue_values; FT_Byte num_other_blues; FT_Byte num_family_blues; FT_Byte num_family_other_blues; FT_Short[14] blue_values; FT_Short[10] other_blues; FT_Short[14] family_blues; FT_Short[10] family_other_blues; FT_Fixed blue_scale; FT_Int blue_shift; FT_Int blue_fuzz; FT_UShort[1] standard_width; FT_UShort[1] standard_height; FT_Byte num_snap_widths; FT_Byte num_snap_heights; FT_Bool force_bold; FT_Bool round_stem_up; FT_Short[13] snap_widths; FT_Short[13] snap_heights; FT_Fixed expansion_factor; FT_Long language_group; FT_Long password; FT_Short[2] min_feature; } alias PS_Private = PS_PrivateRec*; alias T1_Blend_Flags = int; enum { T1_BLEND_UNDERLINE_POSITION = 0, T1_BLEND_UNDERLINE_THICKNESS, T1_BLEND_ITALIC_ANGLE, T1_BLEND_BLUE_VALUES, T1_BLEND_OTHER_BLUES, T1_BLEND_STANDARD_WIDTH, T1_BLEND_STANDARD_HEIGHT, T1_BLEND_STEM_SNAP_WIDTHS, T1_BLEND_STEM_SNAP_HEIGHTS, T1_BLEND_BLUE_SCALE, T1_BLEND_BLUE_SHIFT, T1_BLEND_FAMILY_BLUES, T1_BLEND_FAMILY_OTHER_BLUES, T1_BLEND_FORCE_BOLD, T1_BLEND_MAX } enum T1_MAX_MM_DESIGNS = 16; enum T1_MAX_MM_AXIS = 4; enum T1_MAX_MM_MAP_POINTS = 20; struct PS_DesignMapRec { FT_Byte num_points; FT_Long* design_points; FT_Fixed* blend_points; } alias PS_DesignMap = PS_DesignMapRec*; struct PS_BlendRec { FT_UInt num_designs; FT_UInt num_axis; FT_String*[T1_MAX_MM_AXIS] axis_names; FT_Fixed*[T1_MAX_MM_DESIGNS] design_pos; PS_DesignMapRec[T1_MAX_MM_AXIS] design_map; FT_Fixed* weight_vector; FT_Fixed* default_weight_vector; PS_FontInfo[T1_MAX_MM_DESIGNS+1] font_infos; PS_Private[T1_MAX_MM_DESIGNS+1] privates; FT_ULong blend_bitflags; FT_BBox*[T1_MAX_MM_DESIGNS+1] bboxes; FT_UInt[T1_MAX_MM_DESIGNS] default_design_vector; FT_UInt num_default_design_vector; } alias PS_Blend = PS_BlendRec*; struct CID_FaceDictRec { PS_PrivateRec private_dict; FT_UInt len_buildchar; FT_Fixed forcebold_threshold; FT_Pos stroke_width; FT_Fixed expansion_factor; FT_Byte paint_type; FT_Byte font_type; FT_Matrix font_matrix; FT_Vector font_offset; FT_UInt num_subrs; FT_ULong subrmap_offset; FT_Int sd_bytes; } alias CID_FaceDict = CID_FaceDictRec*; struct CID_FaceInfoRec { FT_String* cid_font_name; FT_Fixed cid_version; FT_Int cid_font_type; FT_String* registry; FT_String* ordering; FT_Int supplement; PS_FontInfoRec font_info; FT_BBox font_bbox; FT_ULong uid_base; FT_Int num_xuid; FT_ULong[16] xuid; FT_ULong cidmap_offset; FT_Int fd_bytes; FT_Int gd_bytes; FT_ULong cid_count; FT_Int num_dicts; CID_FaceDict font_dicts; FT_ULong data_offset; } alias CID_FaceInfo = CID_FaceInfoRec*; alias T1_EncodingType = int; enum { T1_ENCODING_TYPE_NONE = 0, T1_ENCODING_TYPE_ARRAY, T1_ENCODING_TYPE_STANDARD, T1_ENCODING_TYPE_ISOLATIN1, T1_ENCODING_TYPE_EXPERT, } alias PS_Dict_Keys = int; enum { PS_DICT_FONT_TYPE, PS_DICT_FONT_MATRIX, PS_DICT_FONT_BBOX, PS_DICT_PAINT_TYPE, PS_DICT_FONT_NAME, PS_DICT_UNIQUE_ID, PS_DICT_NUM_CHAR_STRINGS, PS_DICT_CHAR_STRING_KEY, PS_DICT_CHAR_STRING, PS_DICT_ENCODING_TYPE, PS_DICT_ENCODING_ENTRY, PS_DICT_NUM_SUBRS, PS_DICT_SUBR, PS_DICT_STD_HW, PS_DICT_STD_VW, PS_DICT_NUM_BLUE_VALUES, PS_DICT_BLUE_VALUE, PS_DICT_BLUE_FUZZ, PS_DICT_NUM_OTHER_BLUES, PS_DICT_OTHER_BLUE, PS_DICT_NUM_FAMILY_BLUES, PS_DICT_FAMILY_BLUE, PS_DICT_NUM_FAMILY_OTHER_BLUES, PS_DICT_FAMILY_OTHER_BLUE, PS_DICT_BLUE_SCALE, PS_DICT_BLUE_SHIFT, PS_DICT_NUM_STEM_SNAP_H, PS_DICT_STEM_SNAP_H, PS_DICT_NUM_STEM_SNAP_V, PS_DICT_STEM_SNAP_V, PS_DICT_FORCE_BOLD, PS_DICT_RND_STEM_UP, PS_DICT_MIN_FEATURE, PS_DICT_LEN_IV, PS_DICT_PASSWORD, PS_DICT_LANGUAGE_GROUP, PS_DICT_VERSION, PS_DICT_NOTICE, PS_DICT_FULL_NAME, PS_DICT_FAMILY_NAME, PS_DICT_WEIGHT, PS_DICT_IS_FIXED_PITCH, PS_DICT_UNDERLINE_POSITION, PS_DICT_UNDERLINE_THICKNESS, PS_DICT_FS_TYPE, PS_DICT_ITALIC_ANGLE, PS_DICT_MAX = PS_DICT_ITALIC_ANGLE } // ttnameid.h enum { TT_PLATFORM_APPLE_UNICODE = 0, TT_PLATFORM_MACINTOSH = 1, TT_PLATFORM_MICROSOFT = 3, TT_PLATFORM_CUSTOM = 4, TT_PLATFORM_ADOBE = 7, } enum { TT_APPLE_ID_DEFAULT = 0, TT_APPLE_ID_UNICODE_1_1 = 1, TT_APPLE_ID_UNICODE_2_0 = 3, TT_APPLE_ID_UNICODE_32 = 4, TT_APPLE_ID_VARIANT_SELECTOR = 5, } enum { TT_MAC_ID_ROMAN = 0, TT_MAC_ID_JAPANESE = 1, TT_MAC_ID_TRADITIONAL_CHINESE = 2, TT_MAC_ID_KOREAN = 3, TT_MAC_ID_ARABIC = 4, TT_MAC_ID_HEBREW = 5, TT_MAC_ID_GREEK = 6, TT_MAC_ID_RUSSIAN = 7, TT_MAC_ID_RSYMBOL = 8, TT_MAC_ID_DEVANAGARI = 9, TT_MAC_ID_GURMUKHI = 10, TT_MAC_ID_GUJARATI = 11, TT_MAC_ID_ORIYA = 12, TT_MAC_ID_BENGALI = 13, TT_MAC_ID_TAMIL = 14, TT_MAC_ID_TELUGU = 15, TT_MAC_ID_KANNADA = 16, TT_MAC_ID_MALAYALAM = 17, TT_MAC_ID_SINHALESE = 18, TT_MAC_ID_BURMESE = 19, TT_MAC_ID_KHMER = 20, TT_MAC_ID_THAI = 21, TT_MAC_ID_LAOTIAN = 22, TT_MAC_ID_GEORGIAN = 23, TT_MAC_ID_ARMENIAN = 24, TT_MAC_ID_MALDIVIAN = 25, TT_MAC_ID_SIMPLIFIED_CHINESE = 25, TT_MAC_ID_TIBETAN = 26, TT_MAC_ID_MONGOLIAN = 27, TT_MAC_ID_GEEZ = 28, TT_MAC_ID_SLAVIC = 29, TT_MAC_ID_VIETNAMESE = 30, TT_MAC_ID_SINDHI = 31, TT_MAC_ID_UNINTERP = 32, } enum { TT_ISO_ID_7BIT_ASCII = 0, TT_ISO_ID_10646 = 1, TT_ISO_ID_8859_1 = 2, } enum { TT_MS_ID_SYMBOL_CS = 0, TT_MS_ID_UNICODE_CS = 1, TT_MS_ID_SJIS = 2, TT_MS_ID_GB2312 = 3, TT_MS_ID_BIG_5 = 4, TT_MS_ID_WANSUNG = 5, TT_MS_ID_JOHAB = 6, TT_MS_ID_UCS_4 = 10, } enum { TT_ADOBE_ID_STANDARD = 0, TT_ADOBE_ID_EXPERT = 1, TT_ADOBE_ID_CUSTOM = 2, TT_ADOBE_ID_LATIN_1 = 3, } enum { TT_MAC_LANGID_ENGLISH = 0, TT_MAC_LANGID_FRENCH = 1, TT_MAC_LANGID_GERMAN = 2, TT_MAC_LANGID_ITALIAN = 3, TT_MAC_LANGID_DUTCH = 4, TT_MAC_LANGID_SWEDISH = 5, TT_MAC_LANGID_SPANISH = 6, TT_MAC_LANGID_DANISH = 7, TT_MAC_LANGID_PORTUGUESE = 8, TT_MAC_LANGID_NORWEGIAN = 9, TT_MAC_LANGID_HEBREW = 10, TT_MAC_LANGID_JAPANESE = 11, TT_MAC_LANGID_ARABIC = 12, TT_MAC_LANGID_FINNISH = 13, TT_MAC_LANGID_GREEK = 14, TT_MAC_LANGID_ICELANDIC = 15, TT_MAC_LANGID_MALTESE = 16, TT_MAC_LANGID_TURKISH = 17, TT_MAC_LANGID_CROATIAN = 18, TT_MAC_LANGID_CHINESE_TRADITIONAL = 19, TT_MAC_LANGID_URDU = 20, TT_MAC_LANGID_HINDI = 21, TT_MAC_LANGID_THAI = 22, TT_MAC_LANGID_KOREAN = 23, TT_MAC_LANGID_LITHUANIAN = 24, TT_MAC_LANGID_POLISH = 25, TT_MAC_LANGID_HUNGARIAN = 26, TT_MAC_LANGID_ESTONIAN = 27, TT_MAC_LANGID_LETTISH = 28, TT_MAC_LANGID_SAAMISK = 29, TT_MAC_LANGID_FAEROESE = 30, TT_MAC_LANGID_FARSI = 31, TT_MAC_LANGID_RUSSIAN = 32, TT_MAC_LANGID_CHINESE_SIMPLIFIED = 33, TT_MAC_LANGID_FLEMISH = 34, TT_MAC_LANGID_IRISH = 35, TT_MAC_LANGID_ALBANIAN = 36, TT_MAC_LANGID_ROMANIAN = 37, TT_MAC_LANGID_CZECH = 38, TT_MAC_LANGID_SLOVAK = 39, TT_MAC_LANGID_SLOVENIAN = 40, TT_MAC_LANGID_YIDDISH = 41, TT_MAC_LANGID_SERBIAN = 42, TT_MAC_LANGID_MACEDONIAN = 43, TT_MAC_LANGID_BULGARIAN = 44, TT_MAC_LANGID_UKRAINIAN = 45, TT_MAC_LANGID_BYELORUSSIAN = 46, TT_MAC_LANGID_UZBEK = 47, TT_MAC_LANGID_KAZAKH = 48, TT_MAC_LANGID_AZERBAIJANI = 49, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT = 49, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT = 50, TT_MAC_LANGID_ARMENIAN = 51, TT_MAC_LANGID_GEORGIAN = 52, TT_MAC_LANGID_MOLDAVIAN = 53, TT_MAC_LANGID_KIRGHIZ = 54, TT_MAC_LANGID_TAJIKI = 55, TT_MAC_LANGID_TURKMEN = 56, TT_MAC_LANGID_MONGOLIAN = 57, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT = 57, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT = 58, TT_MAC_LANGID_PASHTO = 59, TT_MAC_LANGID_KURDISH = 60, TT_MAC_LANGID_KASHMIRI = 61, TT_MAC_LANGID_SINDHI = 62, TT_MAC_LANGID_TIBETAN = 63, TT_MAC_LANGID_NEPALI = 64, TT_MAC_LANGID_SANSKRIT = 65, TT_MAC_LANGID_MARATHI = 66, TT_MAC_LANGID_BENGALI = 67, TT_MAC_LANGID_ASSAMESE = 68, TT_MAC_LANGID_GUJARATI = 69, TT_MAC_LANGID_PUNJABI = 70, TT_MAC_LANGID_ORIYA = 71, TT_MAC_LANGID_MALAYALAM = 72, TT_MAC_LANGID_KANNADA = 73, TT_MAC_LANGID_TAMIL = 74, TT_MAC_LANGID_TELUGU = 75, TT_MAC_LANGID_SINHALESE = 76, TT_MAC_LANGID_BURMESE = 77, TT_MAC_LANGID_KHMER = 78, TT_MAC_LANGID_LAO = 79, TT_MAC_LANGID_VIETNAMESE = 80, TT_MAC_LANGID_INDONESIAN = 81, TT_MAC_LANGID_TAGALOG = 82, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT = 83, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT = 84, TT_MAC_LANGID_AMHARIC = 85, TT_MAC_LANGID_TIGRINYA = 86, TT_MAC_LANGID_GALLA = 87, TT_MAC_LANGID_SOMALI = 88, TT_MAC_LANGID_SWAHILI = 89, TT_MAC_LANGID_RUANDA = 90, TT_MAC_LANGID_RUNDI = 91, TT_MAC_LANGID_CHEWA = 92, TT_MAC_LANGID_MALAGASY = 93, TT_MAC_LANGID_ESPERANTO = 94, TT_MAC_LANGID_WELSH = 128, TT_MAC_LANGID_BASQUE = 129, TT_MAC_LANGID_CATALAN = 130, TT_MAC_LANGID_LATIN = 131, TT_MAC_LANGID_QUECHUA = 132, TT_MAC_LANGID_GUARANI = 133, TT_MAC_LANGID_AYMARA = 134, TT_MAC_LANGID_TATAR = 135, TT_MAC_LANGID_UIGHUR = 136, TT_MAC_LANGID_DZONGKHA = 137, TT_MAC_LANGID_JAVANESE = 138, TT_MAC_LANGID_SUNDANESE = 139, TT_MAC_LANGID_GALICIAN = 140, TT_MAC_LANGID_AFRIKAANS = 141, TT_MAC_LANGID_BRETON = 142, TT_MAC_LANGID_INUKTITUT = 143, TT_MAC_LANGID_SCOTTISH_GAELIC = 144, TT_MAC_LANGID_MANX_GAELIC = 145, TT_MAC_LANGID_IRISH_GAELIC = 146, TT_MAC_LANGID_TONGAN = 147, TT_MAC_LANGID_GREEK_POLYTONIC = 148, TT_MAC_LANGID_GREELANDIC = 149, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT = 150, } enum { TT_MS_LANGID_ARABIC_GENERAL = 0x0001, TT_MS_LANGID_ARABIC_SAUDI_ARABIA = 0x0401, TT_MS_LANGID_ARABIC_IRAQ = 0x0801, TT_MS_LANGID_ARABIC_EGYPT = 0x0c01, TT_MS_LANGID_ARABIC_LIBYA = 0x1001, TT_MS_LANGID_ARABIC_ALGERIA = 0x1401, TT_MS_LANGID_ARABIC_MOROCCO = 0x1801, TT_MS_LANGID_ARABIC_TUNISIA = 0x1c01, TT_MS_LANGID_ARABIC_OMAN = 0x2001, TT_MS_LANGID_ARABIC_YEMEN = 0x2401, TT_MS_LANGID_ARABIC_SYRIA = 0x2801, TT_MS_LANGID_ARABIC_JORDAN = 0x2c01, TT_MS_LANGID_ARABIC_LEBANON = 0x3001, TT_MS_LANGID_ARABIC_KUWAIT = 0x3401, TT_MS_LANGID_ARABIC_UAE = 0x3801, TT_MS_LANGID_ARABIC_BAHRAIN = 0x3c01, TT_MS_LANGID_ARABIC_QATAR = 0x4001, TT_MS_LANGID_BULGARIAN_BULGARIA = 0x0402, TT_MS_LANGID_CATALAN_SPAIN = 0x0403, TT_MS_LANGID_CHINESE_GENERAL = 0x0004, TT_MS_LANGID_CHINESE_TAIWAN = 0x0404, TT_MS_LANGID_CHINESE_PRC = 0x0804, TT_MS_LANGID_CHINESE_HONG_KONG = 0x0c04, TT_MS_LANGID_CHINESE_SINGAPORE = 0x1004, TT_MS_LANGID_CHINESE_MACAU = 0x1404, TT_MS_LANGID_CZECH_CZECH_REPUBLIC = 0x0405, TT_MS_LANGID_DANISH_DENMARK = 0x0406, TT_MS_LANGID_GERMAN_GERMANY = 0x0407, TT_MS_LANGID_GERMAN_SWITZERLAND = 0x0807, TT_MS_LANGID_GERMAN_AUSTRIA = 0x0c07, TT_MS_LANGID_GERMAN_LUXEMBOURG = 0x1007, TT_MS_LANGID_GERMAN_LIECHTENSTEI = 0x1407, TT_MS_LANGID_GREEK_GREECE = 0x0408, TT_MS_LANGID_ENGLISH_GENERAL = 0x0009, TT_MS_LANGID_ENGLISH_UNITED_STATES = 0x0409, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM = 0x0809, TT_MS_LANGID_ENGLISH_AUSTRALIA = 0x0c09, TT_MS_LANGID_ENGLISH_CANADA = 0x1009, TT_MS_LANGID_ENGLISH_NEW_ZEALAND = 0x1409, TT_MS_LANGID_ENGLISH_IRELAND = 0x1809, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA = 0x1c09, TT_MS_LANGID_ENGLISH_JAMAICA = 0x2009, TT_MS_LANGID_ENGLISH_CARIBBEAN = 0x2409, TT_MS_LANGID_ENGLISH_BELIZE = 0x2809, TT_MS_LANGID_ENGLISH_TRINIDAD = 0x2c09, TT_MS_LANGID_ENGLISH_ZIMBABWE = 0x3009, TT_MS_LANGID_ENGLISH_PHILIPPINES = 0x3409, TT_MS_LANGID_ENGLISH_INDONESIA = 0x3809, TT_MS_LANGID_ENGLISH_HONG_KONG = 0x3c09, TT_MS_LANGID_ENGLISH_INDIA = 0x4009, TT_MS_LANGID_ENGLISH_MALAYSIA = 0x4409, TT_MS_LANGID_ENGLISH_SINGAPORE = 0x4809, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT = 0x040a, TT_MS_LANGID_SPANISH_MEXICO = 0x080a, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT = 0x0c0a, TT_MS_LANGID_SPANISH_GUATEMALA = 0x100a, TT_MS_LANGID_SPANISH_COSTA_RICA = 0x140a, TT_MS_LANGID_SPANISH_PANAMA = 0x180a, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC = 0x1c0a, TT_MS_LANGID_SPANISH_VENEZUELA = 0x200a, TT_MS_LANGID_SPANISH_COLOMBIA = 0x240a, TT_MS_LANGID_SPANISH_PERU = 0x280a, TT_MS_LANGID_SPANISH_ARGENTINA = 0x2c0a, TT_MS_LANGID_SPANISH_ECUADOR = 0x300a, TT_MS_LANGID_SPANISH_CHILE = 0x340a, TT_MS_LANGID_SPANISH_URUGUAY = 0x380a, TT_MS_LANGID_SPANISH_PARAGUAY = 0x3c0a, TT_MS_LANGID_SPANISH_BOLIVIA = 0x400a, TT_MS_LANGID_SPANISH_EL_SALVADOR = 0x440a, TT_MS_LANGID_SPANISH_HONDURAS = 0x480a, TT_MS_LANGID_SPANISH_NICARAGUA = 0x4c0a, TT_MS_LANGID_SPANISH_PUERTO_RICO = 0x500a, TT_MS_LANGID_SPANISH_UNITED_STATES = 0x540a, TT_MS_LANGID_SPANISH_LATIN_AMERICA = 0xE40aU, TT_MS_LANGID_FINNISH_FINLAND = 0x040b, TT_MS_LANGID_FRENCH_FRANCE = 0x040c, TT_MS_LANGID_FRENCH_BELGIUM = 0x080c, TT_MS_LANGID_FRENCH_CANADA = 0x0c0c, TT_MS_LANGID_FRENCH_SWITZERLAND = 0x100c, TT_MS_LANGID_FRENCH_LUXEMBOURG = 0x140c, TT_MS_LANGID_FRENCH_MONACO = 0x180c, TT_MS_LANGID_FRENCH_WEST_INDIES = 0x1c0c, TT_MS_LANGID_FRENCH_REUNION = 0x200c, TT_MS_LANGID_FRENCH_CONGO = 0x240c, TT_MS_LANGID_FRENCH_ZAIRE = TT_MS_LANGID_FRENCH_CONGO, TT_MS_LANGID_FRENCH_SENEGAL = 0x280c, TT_MS_LANGID_FRENCH_CAMEROON = 0x2c0c, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE = 0x300c, TT_MS_LANGID_FRENCH_MALI = 0x340c, TT_MS_LANGID_FRENCH_MOROCCO = 0x380c, TT_MS_LANGID_FRENCH_HAITI = 0x3c0c, TT_MS_LANGID_FRENCH_NORTH_AFRICA = 0xE40cU, TT_MS_LANGID_HEBREW_ISRAEL = 0x040d, TT_MS_LANGID_HUNGARIAN_HUNGARY = 0x040e, TT_MS_LANGID_ICELANDIC_ICELAND = 0x040f, TT_MS_LANGID_ITALIAN_ITALY = 0x0410, TT_MS_LANGID_ITALIAN_SWITZERLAND = 0x0810, TT_MS_LANGID_JAPANESE_JAPAN = 0x0411, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA = 0x0412, TT_MS_LANGID_KOREAN_JOHAB_KOREA = 0x0812, TT_MS_LANGID_DUTCH_NETHERLANDS = 0x0413, TT_MS_LANGID_DUTCH_BELGIUM = 0x0813, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL = 0x0414, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK = 0x0814, TT_MS_LANGID_POLISH_POLAND = 0x0415, TT_MS_LANGID_PORTUGUESE_BRAZIL = 0x0416, TT_MS_LANGID_PORTUGUESE_PORTUGAL = 0x0816, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND = 0x0417, TT_MS_LANGID_ROMANIAN_ROMANIA = 0x0418, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA = 0x0818, TT_MS_LANGID_RUSSIAN_RUSSIA = 0x0419, TT_MS_LANGID_RUSSIAN_MOLDAVIA = 0x0819, TT_MS_LANGID_CROATIAN_CROATIA = 0x041a, TT_MS_LANGID_SERBIAN_SERBIA_LATIN = 0x081a, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC = 0x0c1a, TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA = 0x101a, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA = 0x141a, TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN = 0x181a, TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC = 0x181a, TT_MS_LANGID_SLOVAK_SLOVAKIA = 0x041b, TT_MS_LANGID_ALBANIAN_ALBANIA = 0x041c, TT_MS_LANGID_SWEDISH_SWEDEN = 0x041d, TT_MS_LANGID_SWEDISH_FINLAND = 0x081d, TT_MS_LANGID_THAI_THAILAND = 0x041e, TT_MS_LANGID_TURKISH_TURKEY = 0x041f, TT_MS_LANGID_URDU_PAKISTAN = 0x0420, TT_MS_LANGID_URDU_INDIA = 0x0820, TT_MS_LANGID_INDONESIAN_INDONESIA = 0x0421, TT_MS_LANGID_UKRAINIAN_UKRAINE = 0x0422, TT_MS_LANGID_BELARUSIAN_BELARUS = 0x0423, TT_MS_LANGID_SLOVENE_SLOVENIA = 0x0424, TT_MS_LANGID_ESTONIAN_ESTONIA = 0x0425, TT_MS_LANGID_LATVIAN_LATVIA = 0x0426, TT_MS_LANGID_LITHUANIAN_LITHUANIA = 0x0427, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA = 0x0827, TT_MS_LANGID_TAJIK_TAJIKISTAN = 0x0428, TT_MS_LANGID_FARSI_IRAN = 0x0429, TT_MS_LANGID_VIETNAMESE_VIET_NAM = 0x042a, TT_MS_LANGID_ARMENIAN_ARMENIA = 0x042b, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN = 0x042c, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC = 0x082c, TT_MS_LANGID_BASQUE_SPAIN = 0x042d, TT_MS_LANGID_SORBIAN_GERMANY = 0x042e, TT_MS_LANGID_MACEDONIAN_MACEDONIA = 0x042f, TT_MS_LANGID_SUTU_SOUTH_AFRICA = 0x0430, TT_MS_LANGID_TSONGA_SOUTH_AFRICA = 0x0431, TT_MS_LANGID_TSWANA_SOUTH_AFRICA = 0x0432, TT_MS_LANGID_VENDA_SOUTH_AFRICA = 0x0433, TT_MS_LANGID_XHOSA_SOUTH_AFRICA = 0x0434, TT_MS_LANGID_ZULU_SOUTH_AFRICA = 0x0435, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA = 0x0436, TT_MS_LANGID_GEORGIAN_GEORGIA = 0x0437, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS = 0x0438, TT_MS_LANGID_HINDI_INDIA = 0x0439, TT_MS_LANGID_MALTESE_MALTA = 0x043a, TT_MS_LANGID_SAMI_NORTHERN_NORWAY = 0x043b, TT_MS_LANGID_SAMI_NORTHERN_SWEDEN = 0x083b, TT_MS_LANGID_SAMI_NORTHERN_FINLAND = 0x0C3b, TT_MS_LANGID_SAMI_LULE_NORWAY = 0x103b, TT_MS_LANGID_SAMI_LULE_SWEDEN = 0x143b, TT_MS_LANGID_SAMI_SOUTHERN_NORWAY = 0x183b, TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN = 0x1C3b, TT_MS_LANGID_SAMI_SKOLT_FINLAND = 0x203b, TT_MS_LANGID_SAMI_INARI_FINLAND = 0x243b, TT_MS_LANGID_SAAMI_LAPONIA = 0x043b, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM = 0x083c, TT_MS_LANGID_IRISH_GAELIC_IRELAND = 0x043c, TT_MS_LANGID_YIDDISH_GERMANY = 0x043d, TT_MS_LANGID_MALAY_MALAYSIA = 0x043e, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM = 0x083e, TT_MS_LANGID_KAZAK_KAZAKSTAN = 0x043f, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN = 0x0440, TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC = TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN, TT_MS_LANGID_SWAHILI_KENYA = 0x0441, TT_MS_LANGID_TURKMEN_TURKMENISTAN = 0x0442, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN = 0x0443, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC = 0x0843, TT_MS_LANGID_TATAR_TATARSTAN = 0x0444, TT_MS_LANGID_BENGALI_INDIA = 0x0445, TT_MS_LANGID_BENGALI_BANGLADESH = 0x0845, TT_MS_LANGID_PUNJABI_INDIA = 0x0446, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN = 0x0846, TT_MS_LANGID_GUJARATI_INDIA = 0x0447, TT_MS_LANGID_ORIYA_INDIA = 0x0448, TT_MS_LANGID_TAMIL_INDIA = 0x0449, TT_MS_LANGID_TELUGU_INDIA = 0x044a, TT_MS_LANGID_KANNADA_INDIA = 0x044b, TT_MS_LANGID_MALAYALAM_INDIA = 0x044c, TT_MS_LANGID_ASSAMESE_INDIA = 0x044d, TT_MS_LANGID_MARATHI_INDIA = 0x044e, TT_MS_LANGID_SANSKRIT_INDIA = 0x044f, TT_MS_LANGID_MONGOLIAN_MONGOLIA = 0x0450, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN = 0x0850, TT_MS_LANGID_TIBETAN_CHINA = 0x0451, TT_MS_LANGID_DZONGHKA_BHUTAN = 0x0851, TT_MS_LANGID_TIBETAN_BHUTAN = TT_MS_LANGID_DZONGHKA_BHUTAN, TT_MS_LANGID_WELSH_WALES = 0x0452, TT_MS_LANGID_KHMER_CAMBODIA = 0x0453, TT_MS_LANGID_LAO_LAOS = 0x0454, TT_MS_LANGID_BURMESE_MYANMAR = 0x0455, TT_MS_LANGID_GALICIAN_SPAIN = 0x0456, TT_MS_LANGID_KONKANI_INDIA = 0x0457, TT_MS_LANGID_MANIPURI_INDIA = 0x0458, TT_MS_LANGID_SINDHI_INDIA = 0x0459, TT_MS_LANGID_SINDHI_PAKISTAN = 0x0859, TT_MS_LANGID_SYRIAC_SYRIA = 0x045a, TT_MS_LANGID_SINHALESE_SRI_LANKA = 0x045b, TT_MS_LANGID_CHEROKEE_UNITED_STATES = 0x045c, TT_MS_LANGID_INUKTITUT_CANADA = 0x045d, TT_MS_LANGID_AMHARIC_ETHIOPIA = 0x045e, TT_MS_LANGID_TAMAZIGHT_MOROCCO = 0x045f, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN = 0x085f, TT_MS_LANGID_KASHMIRI_PAKISTAN = 0x0460, TT_MS_LANGID_KASHMIRI_SASIA = 0x0860, TT_MS_LANGID_KASHMIRI_INDIA = TT_MS_LANGID_KASHMIRI_SASIA, TT_MS_LANGID_NEPALI_NEPAL = 0x0461, TT_MS_LANGID_NEPALI_INDIA = 0x0861, TT_MS_LANGID_FRISIAN_NETHERLANDS = 0x0462, TT_MS_LANGID_PASHTO_AFGHANISTAN = 0x0463, TT_MS_LANGID_FILIPINO_PHILIPPINES = 0x0464, TT_MS_LANGID_DHIVEHI_MALDIVES = 0x0465, TT_MS_LANGID_DIVEHI_MALDIVES = TT_MS_LANGID_DHIVEHI_MALDIVES, TT_MS_LANGID_EDO_NIGERIA = 0x0466, TT_MS_LANGID_FULFULDE_NIGERIA = 0x0467, TT_MS_LANGID_HAUSA_NIGERIA = 0x0468, TT_MS_LANGID_IBIBIO_NIGERIA = 0x0469, TT_MS_LANGID_YORUBA_NIGERIA = 0x046a, TT_MS_LANGID_QUECHUA_BOLIVIA = 0x046b, TT_MS_LANGID_QUECHUA_ECUADOR = 0x086b, TT_MS_LANGID_QUECHUA_PERU = 0x0c6b, TT_MS_LANGID_SEPEDI_SOUTH_AFRICA = 0x046c, TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA = TT_MS_LANGID_SEPEDI_SOUTH_AFRICA, TT_MS_LANGID_IGBO_NIGERIA = 0x0470, TT_MS_LANGID_KANURI_NIGERIA = 0x0471, TT_MS_LANGID_OROMO_ETHIOPIA = 0x0472, TT_MS_LANGID_TIGRIGNA_ETHIOPIA = 0x0473, TT_MS_LANGID_TIGRIGNA_ERYTHREA = 0x0873, TT_MS_LANGID_TIGRIGNA_ERYTREA = TT_MS_LANGID_TIGRIGNA_ERYTHREA, TT_MS_LANGID_GUARANI_PARAGUAY = 0x0474, TT_MS_LANGID_HAWAIIAN_UNITED_STATES = 0x0475, TT_MS_LANGID_LATIN = 0x0476, TT_MS_LANGID_SOMALI_SOMALIA = 0x0477, TT_MS_LANGID_YI_CHINA = 0x0478, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES = 0x0479, TT_MS_LANGID_UIGHUR_CHINA = 0x0480, TT_MS_LANGID_MAORI_NEW_ZEALAND = 0x0481, } enum { TT_NAME_ID_COPYRIGHT = 0, TT_NAME_ID_FONT_FAMILY = 1, TT_NAME_ID_FONT_SUBFAMILY = 2, TT_NAME_ID_UNIQUE_ID = 3, TT_NAME_ID_FULL_NAME = 4, TT_NAME_ID_VERSION_STRING = 5, TT_NAME_ID_PS_NAME = 6, TT_NAME_ID_TRADEMARK = 7, TT_NAME_ID_MANUFACTURER = 8, TT_NAME_ID_DESIGNER = 9, TT_NAME_ID_DESCRIPTION = 10, TT_NAME_ID_VENDOR_URL = 11, TT_NAME_ID_DESIGNER_URL = 12, TT_NAME_ID_LICENSE = 13, TT_NAME_ID_LICENSE_URL = 14, TT_NAME_ID_PREFERRED_FAMILY = 16, TT_NAME_ID_PREFERRED_SUBFAMILY = 17, TT_NAME_ID_MAC_FULL_NAME = 18, TT_NAME_ID_SAMPLE_TEXT = 19, TT_NAME_ID_CID_FINDFONT_NAME = 20, TT_NAME_ID_WWS_FAMILY = 21, TT_NAME_ID_WWS_SUBFAMILY = 22, } enum { TT_UCR_BASIC_LATIN = 1 << 0, TT_UCR_LATIN1_SUPPLEMENT = 1 << 1, TT_UCR_LATIN_EXTENDED_A = 1 << 2, TT_UCR_LATIN_EXTENDED_B = 1 << 3, TT_UCR_IPA_EXTENSIONS = 1 << 4, TT_UCR_SPACING_MODIFIER = 1 << 5, TT_UCR_COMBINING_DIACRITICS = 1 << 6, TT_UCR_GREEK = 1 << 7, TT_UCR_COPTIC = 1 << 8, TT_UCR_CYRILLIC = 1 << 9, TT_UCR_ARMENIAN = 1 << 10, TT_UCR_HEBREW = 1 << 11, TT_UCR_VAI = 1 << 12, TT_UCR_ARABIC = 1 << 13, TT_UCR_NKO = 1 << 14, TT_UCR_DEVANAGARI = 1 << 15, TT_UCR_BENGALI = 1 << 16, TT_UCR_GURMUKHI = 1 << 17, TT_UCR_GUJARATI = 1 << 18, TT_UCR_ORIYA = 1 << 19, TT_UCR_TAMIL = 1 << 20, TT_UCR_TELUGU = 1 << 21, TT_UCR_KANNADA = 1 << 22, TT_UCR_MALAYALAM = 1 << 23, TT_UCR_THAI = 1 << 24, TT_UCR_LAO = 1 << 25, TT_UCR_GEORGIAN = 1 << 26, TT_UCR_BALINESE = 1 << 27, TT_UCR_HANGUL_JAMO = 1 << 28, TT_UCR_LATIN_EXTENDED_ADDITIONAL = 1 << 29, TT_UCR_GREEK_EXTENDED = 1 << 30, TT_UCR_SUPERSCRIPTS_SUBSCRIPTS = 1 << 0, TT_UCR_CURRENCY_SYMBOLS = 1 << 1, TT_UCR_COMBINING_DIACRITICS_SYMB = 1 << 2, TT_UCR_LETTERLIKE_SYMBOLS = 1 << 3, TT_UCR_NUMBER_FORMS = 1 << 4, TT_UCR_ARROWS = 1 << 5, TT_UCR_MATHEMATICAL_OPERATORS = 1 << 6, TT_UCR_MISCELLANEOUS_TECHNICAL = 1 << 7, TT_UCR_CONTROL_PICTURES = 1 << 8, TT_UCR_OCR = 1 << 9, TT_UCR_ENCLOSED_ALPHANUMERICS = 1 << 10, TT_UCR_BOX_DRAWING = 1 << 11, TT_UCR_BLOCK_ELEMENTS = 1 << 12, TT_UCR_GEOMETRIC_SHAPES = 1 << 13, TT_UCR_MISCELLANEOUS_SYMBOLS = 1 << 14, TT_UCR_DINGBATS = 1 << 15, TT_UCR_CJK_SYMBOLS = 1 << 16, TT_UCR_HIRAGANA = 1 << 17, TT_UCR_KATAKANA = 1 << 18, TT_UCR_BOPOMOFO = 1 << 19, TT_UCR_HANGUL_COMPATIBILITY_JAMO = 1 << 20, TT_UCR_CJK_MISC = 1 << 21, TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS = 1 << 22, TT_UCR_CJK_COMPATIBILITY = 1 << 23, TT_UCR_HANGUL = 1 << 24, TT_UCR_SURROGATES = 1 << 25, TT_UCR_NON_PLANE_0 = TT_UCR_SURROGATES, TT_UCR_PHOENICIAN = 1 << 26, TT_UCR_CJK_UNIFIED_IDEOGRAPHS = 1 << 27, TT_UCR_PRIVATE_USE = 1 << 28, TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS = 1 << 29, TT_UCR_ALPHABETIC_PRESENTATION_FORMS = 1 << 30, TT_UCR_ARABIC_PRESENTATIONS_A = 1 << 31, TT_UCR_COMBINING_HALF_MARKS = 1 << 0, TT_UCR_CJK_COMPATIBILITY_FORMS = 1 << 1, TT_UCR_SMALL_FORM_VARIANTS = 1 << 2, TT_UCR_ARABIC_PRESENTATIONS_B = 1 << 3, TT_UCR_HALFWIDTH_FULLWIDTH_FORMS = 1 << 4, TT_UCR_SPECIALS = 1 << 5, TT_UCR_TIBETAN = 1 << 6, TT_UCR_SYRIAC = 1 << 7, TT_UCR_THAANA = 1 << 8, TT_UCR_SINHALA = 1 << 9, TT_UCR_MYANMAR = 1 << 10, TT_UCR_ETHIOPIC = 1 << 11, TT_UCR_CHEROKEE = 1 << 12, TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS = 1 << 13, TT_UCR_OGHAM = 1 << 14, TT_UCR_RUNIC = 1 << 15, TT_UCR_KHMER = 1 << 16, TT_UCR_MONGOLIAN = 1 << 17, TT_UCR_BRAILLE = 1 << 18, TT_UCR_YI = 1 << 19, TT_UCR_PHILIPPINE = 1 << 20, TT_UCR_OLD_ITALIC = 1 << 21, TT_UCR_GOTHIC = 1 << 22, TT_UCR_DESERET = 1 << 23, TT_UCR_MUSICAL_SYMBOLS = 1 << 24, TT_UCR_MATH_ALPHANUMERIC_SYMBOLS = 1 << 25, TT_UCR_PRIVATE_USE_SUPPLEMENTARY = 1 << 26, TT_UCR_VARIATION_SELECTORS = 1 << 27, TT_UCR_TAGS = 1 << 28, TT_UCR_LIMBU = 1 << 29, TT_UCR_TAI_LE = 1 << 30, TT_UCR_NEW_TAI_LUE = 1 << 31, TT_UCR_BUGINESE = 1 << 0, TT_UCR_GLAGOLITIC = 1 << 1, TT_UCR_TIFINAGH = 1 << 2, TT_UCR_YIJING = 1 << 3, TT_UCR_SYLOTI_NAGRI = 1 << 4, TT_UCR_LINEAR_B = 1 << 5, TT_UCR_ANCIENT_GREEK_NUMBERS = 1 << 6, TT_UCR_UGARITIC = 1 << 7, TT_UCR_OLD_PERSIAN = 1 << 8, TT_UCR_SHAVIAN = 1 << 9, TT_UCR_OSMANYA = 1 << 10, TT_UCR_CYPRIOT_SYLLABARY = 1 << 11, TT_UCR_KHAROSHTHI = 1 << 12, TT_UCR_TAI_XUAN_JING = 1 << 13, TT_UCR_CUNEIFORM = 1 << 14, TT_UCR_COUNTING_ROD_NUMERALS = 1 << 15, TT_UCR_SUNDANESE = 1 << 16, TT_UCR_LEPCHA = 1 << 17, TT_UCR_OL_CHIKI = 1 << 18, TT_UCR_SAURASHTRA = 1 << 19, TT_UCR_KAYAH_LI = 1 << 20, TT_UCR_REJANG = 1 << 21, TT_UCR_CHAM = 1 << 22, TT_UCR_ANCIENT_SYMBOLS = 1 << 23, TT_UCR_PHAISTOS_DISC = 1 << 24, TT_UCR_OLD_ANATOLIAN = 1 << 25, TT_UCR_GAME_TILES = 1 << 26, } // tttables.h struct TT_Header { FT_Fixed Table_Version; FT_Fixed Font_Revision; FT_Long CheckSum_Adjust; FT_Long Magic_Number; FT_UShort Flags; FT_UShort Units_Per_EM; FT_Long[2] Created; FT_Long[2] Modified; FT_Short xMin; FT_Short yMin; FT_Short xMax; FT_Short yMax; FT_UShort Mac_Style; FT_UShort Lowest_Rec_PPEM; FT_Short Font_Direction; FT_Short Index_To_Loc_Format; FT_Short Glyph_Data_Format; } struct TT_HoriHeader { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Width_Max; FT_Short min_Left_Side_Bearing; FT_Short min_Right_Side_Bearing; FT_Short xMax_Extent; FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short[4] Reserved; FT_Short metric_Data_Format; FT_UShort number_Of_HMetrics; void* long_metrics; void* short_metrics; } struct TT_VertHeader { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Height_Max; FT_Short min_Top_Side_Bearing; FT_Short min_Bottom_Side_Bearing; FT_Short yMax_Extent; FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short[4] Reserved; FT_Short metric_Data_Format; FT_UShort number_Of_VMetrics; void* long_metrics; void* short_metrics; } struct TT_OS2 { FT_UShort _version; FT_Short xAvgCharWidth; FT_UShort usWeightClass; FT_UShort usWidthClass; FT_UShort fsType; FT_Short ySubscriptXSize; FT_Short ySubscriptYSize; FT_Short ySubscriptXOffset; FT_Short ySubscriptYOffset; FT_Short ySuperscriptXSize; FT_Short ySuperscriptYSize; FT_Short ySuperscriptXOffset; FT_Short ySuperscriptYOffset; FT_Short yStrikeoutSize; FT_Short yStrikeoutPosition; FT_Short sFamilyClass; FT_Byte[10] panose; FT_ULong ulUnicodeRange1; FT_ULong ulUnicodeRange2; FT_ULong ulUnicodeRange3; FT_ULong ulUnicodeRange4; FT_Char[4] achVendID; FT_UShort fsSelection; FT_UShort usFirstCharIndex; FT_UShort usLastCharIndex; FT_Short sTypoAscender; FT_Short sTypoDescender; FT_Short sTypoLineGap; FT_UShort usWinAscent; FT_UShort usWinDescent; FT_ULong ulCodePageRange1; FT_ULong ulCodePageRange2; FT_Short sxHeight; FT_Short sCapHeight; FT_UShort usDefaultChar; FT_UShort usBreakChar; FT_UShort usMaxContext; FT_UShort usLowerOpticalPointSize; FT_UShort usUpperOpticalPointSize; } struct TT_Postscript { FT_Fixed FormatType; FT_Fixed italicAngle; FT_Short underlinePosition; FT_Short underlineThickness; FT_ULong isFixedPitch; FT_ULong minMemType42; FT_ULong maxMemType42; FT_ULong minMemType1; FT_ULong maxMemType1; } struct TT_PCLT { FT_Fixed Version; FT_ULong FontNumber; FT_UShort Pitch; FT_UShort xHeight; FT_UShort Style; FT_UShort TypeFamily; FT_UShort CapHeight; FT_UShort SymbolSet; FT_Char[16] TypeFace; FT_Char[8] CharacterComplement; FT_Char[6] FileName; FT_Char StrokeWeight; FT_Char WidthType; FT_Byte SerifStyle; FT_Byte Reserved; } struct TT_MaxProfile { FT_Fixed _version; FT_UShort numGlyphs; FT_UShort maxPoints; FT_UShort maxContours; FT_UShort maxCompositePoints; FT_UShort maxCompositeContours; FT_UShort maxZones; FT_UShort maxTwilightPoints; FT_UShort maxStorage; FT_UShort maxFunctionDefs; FT_UShort maxInstructionDefs; FT_UShort maxStackElements; FT_UShort maxSizeOfInstructions; FT_UShort maxComponentElements; FT_UShort maxComponentDepth; } alias FT_Sfnt_Tag = int; enum { FT_SFNT_HEAD, FT_SFNT_MAXP, FT_SFNT_OS2, FT_SFNT_HHEA, FT_SFNT_VHEA, FT_SFNT_POST, FT_SFNT_PCLT, FT_SFNT_MAX } appstream-generator-0.6.8/src/asgen/bindings/gdkpixbuf.d000066400000000000000000000032201320016272000233040ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.gdkpixbuf; import glib.c.types; import gio.c.types; import asgen.bindings.cairo; extern(C): nothrow: @nogc: enum GdkInterpType { NEAREST, TILES, BILINEAR, HYPER }; struct _GdkPixbuf {} alias GdkPixbuf = _GdkPixbuf*; GdkPixbuf gdk_pixbuf_new_from_file (const(char) *filename, GError **error); GdkPixbuf gdk_pixbuf_new_from_stream (GInputStream *stream, GCancellable *cancellable, GError **error); int gdk_pixbuf_get_width (GdkPixbuf pixbuf); int gdk_pixbuf_get_height (GdkPixbuf pixbuf); GdkPixbuf gdk_pixbuf_scale_simple (const(GdkPixbuf) src, int dest_width, int dest_height, GdkInterpType interp_type); bool gdk_pixbuf_save_to_buffer (GdkPixbuf pixbuf, char **buffer, size_t *buffer_size, const(char) *type, GError **error, ...); bool gdk_pixbuf_save (GdkPixbuf pixbuf, const(char) *filename, const(char) *type, GError **error, ...); appstream-generator-0.6.8/src/asgen/bindings/libarchive.d000066400000000000000000000076501320016272000234440ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.libarchive; import core.stdc.stdio; import std.conv : octal; extern(C): nothrow: @nogc: static if (!is(typeof(usize))) private alias usize = size_t; struct archive {} struct archive_entry {} immutable ARCHIVE_EOF = 1; /* Found end of archive. */ immutable ARCHIVE_OK = 0; /* Operation was successful. */ immutable ARCHIVE_RETRY = -10; /* Retry might succeed. */ immutable ARCHIVE_WARN = -20; /* Partial success. */ immutable ARCHIVE_FAILED = -25; /* Current operation cannot complete. */ immutable ARCHIVE_FATAL = -30; /* No more operations are possible. */ immutable AE_IFMT = octal!170000; immutable AE_IFREG = octal!100000; immutable AE_IFLNK = octal!120000; immutable AE_IFSOCK = octal!140000; immutable AE_IFCHR = octal!20000; immutable AE_IFBLK = octal!60000; immutable AE_IFDIR = octal!40000; immutable AE_IFIFO = octal!10000; const(char) *archive_error_string (archive*); int archive_errno (archive*); archive *archive_read_new (); int archive_read_free (archive*); int archive_read_support_filter_all (archive*); int archive_read_support_filter_gzip (archive*); int archive_read_support_filter_lzma (archive*); int archive_read_support_format_raw (archive*); int archive_read_support_format_empty (archive*); int archive_read_support_format_all (archive*); int archive_read_support_format_ar (archive*); int archive_read_support_format_gnutar (archive*); int archive_write_set_filter_option (archive *a, const(char) *m, const(char) *o, const(char) *v); int archive_read_open_filename (archive*, const(char) *filename, usize block_size); int archive_read_open_FILE (archive*, FILE *file); int archive_read_open_memory (archive*, void *buff, size_t size); ptrdiff_t archive_read_data (archive*, void*, usize); int archive_read_next_header (archive*, archive_entry**); int archive_read_data_skip (archive*); int archive_read_data_block (archive *a, const(void*) *buff, size_t *size, long *offset); archive_entry *archive_entry_new (); void archive_entry_free (archive_entry*); const(char) *archive_entry_pathname (archive_entry*); void archive_entry_set_pathname (archive_entry*, const(char) *); uint archive_entry_filetype (archive_entry*); void archive_entry_set_size (archive_entry*, long); void archive_entry_set_filetype (archive_entry*, uint); void archive_entry_set_perm (archive_entry*, uint); void archive_entry_set_mtime (archive_entry*, ulong sec, long nsec); const(char) *archive_entry_symlink (archive_entry*); archive *archive_write_new (); int archive_write_free (archive*); int archive_write_close (archive*); int archive_write_add_filter_gzip (archive*); int archive_write_add_filter_xz (archive*); int archive_write_set_format_pax (archive*); int archive_write_set_format_pax_restricted (archive*); int archive_write_set_format_raw (archive*); //int archive_write_set_format_raw (archive *a); /// Will be available in the next version of libarchive (to be released in 2016) int archive_write_set_format_by_name (archive*, const(char) *name); int archive_write_open_filename (archive*, const(char) *file); int archive_write_header (archive*, archive_entry*); size_t archive_write_data(archive*, const(void)*, size_t); appstream-generator-0.6.8/src/asgen/bindings/lmdb.d000066400000000000000000000156531320016272000222540ustar00rootroot00000000000000/* * @author Howard Chu, Symas Corporation. * * @copyright Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . * * @par Derived From: * This code is derived from btree.c written by Martin Hedenfalk. * * Copyright (c) 2009, 2010 Martin Hedenfalk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ module asgen.bindings.lmdb; // ////////////////////////////////////////////////////////////////////////// // // C API extern(C): nothrow: @nogc: static if (!is(typeof(usize))) private alias usize = size_t; alias mdb_mode_t = uint; struct mdb_filehandle_ts {} alias mdb_filehandle_t = mdb_filehandle_ts*; enum { MDB_VERSION_MAJOR = 0, MDB_VERSION_MINOR = 9, MDB_VERSION_PATCH = 18, MDB_VERSION_DATE = "December 19, 2015", } struct MDB_env_s {} alias MDB_envp = MDB_env_s*; struct MDB_txn_s {} alias MDB_txnp = MDB_txn_s*; alias MDB_dbi = uint; struct MDB_cursor_s {} alias MDB_cursorp = MDB_cursor_s*; struct MDB_val { usize mv_size; void* mv_data; } enum { MDB_FIXEDMAP = 0x01, MDB_NOSUBDIR = 0x4000, MDB_NOSYNC = 0x10000, MDB_RDONLY = 0x20000, MDB_NOMETASYNC = 0x40000, MDB_WRITEMAP = 0x80000, MDB_MAPASYNC = 0x100000, MDB_NOTLS = 0x200000, MDB_NOLOCK = 0x400000, MDB_NORDAHEAD = 0x800000, MDB_NOMEMINIT = 0x1000000 } enum { MDB_REVERSEKEY = 0x02, MDB_DUPSORT = 0x04, MDB_INTEGERKEY = 0x08, MDB_DUPFIXED = 0x10, MDB_INTEGERDUP = 0x20, MDB_REVERSEDUP = 0x40, MDB_CREATE = 0x40000 } enum { MDB_NOOVERWRITE = 0x10, MDB_NODUPDATA = 0x20, MDB_RESERVE = 0x10000, MDB_APPEND = 0x20000, MDB_APPENDDUP = 0x40000, MDB_MULTIPLE = 0x80000 } enum /*MDB_cursor_op*/ { MDB_FIRST, MDB_FIRST_DUP, MDB_GET_BOTH, MDB_GET_BOTH_RANGE, MDB_GET_CURRENT, MDB_GET_MULTIPLE, MDB_LAST, MDB_LAST_DUP, MDB_NEXT, MDB_NEXT_DUP, MDB_NEXT_MULTIPLE, MDB_NEXT_NODUP, MDB_PREV, MDB_PREV_DUP, MDB_PREV_NODUP, MDB_SET, MDB_SET_KEY, MDB_SET_RANGE, } enum { MDB_SUCCESS = 0, MDB_KEYEXIST = (-30799), MDB_NOTFOUND = (-30798), MDB_PAGE_NOTFOUND = (-30797), MDB_CORRUPTED = (-30796), MDB_PANIC = (-30795), MDB_VERSION_MISMATCH = (-30794), MDB_INVALID = (-30793), MDB_MAP_FULL = (-30792), MDB_DBS_FULL = (-30791), MDB_READERS_FULL = (-30790), MDB_TLS_FULL = (-30789), MDB_TXN_FULL = (-30788), MDB_CURSOR_FULL = (-30787), MDB_PAGE_FULL = (-30786), MDB_MAP_RESIZED = (-30785), MDB_INCOMPATIBLE = (-30784), MDB_BAD_RSLOT = (-30783), MDB_BAD_TXN = (-30782), MDB_BAD_VALSIZE = (-30781), MDB_BAD_DBI = (-30780), MDB_LAST_ERRCODE = MDB_BAD_DBI } struct MDB_stat { uint ms_psize; uint ms_depth; usize ms_branch_pages; usize ms_leaf_pages; usize ms_overflow_pages; usize ms_entries; } struct MDB_envinfo { void* me_mapaddr; usize me_mapsize; usize me_last_pgno; usize me_last_txnid; uint me_maxreaders; uint me_numreaders; } const(char)* mdb_version (int* major, int* minor, int* patch); const(char)* mdb_strerror (int err); int mdb_env_create (MDB_envp* env); int mdb_env_open (MDB_envp env, const(char)* path, uint flags, mdb_mode_t mode); int mdb_env_copy (MDB_envp env, const(char)* path); int mdb_env_copyfd (MDB_envp env, mdb_filehandle_t fd); int mdb_env_stat (MDB_envp env, MDB_stat* stat); int mdb_env_info (MDB_envp env, MDB_envinfo* stat); int mdb_env_sync (MDB_envp env, int force); void mdb_env_close (MDB_envp env); int mdb_env_set_flags (MDB_envp env, uint flags, int onoff); int mdb_env_get_flags (MDB_envp env, uint* flags); int mdb_env_get_path (MDB_envp env, const(char)** path); int mdb_env_get_fd (MDB_envp env, mdb_filehandle_t* fd); int mdb_env_set_mapsize (MDB_envp env, usize size); int mdb_env_set_maxreaders (MDB_envp env, uint readers); int mdb_env_get_maxreaders (MDB_envp env, uint* readers); int mdb_env_set_maxdbs (MDB_envp env, MDB_dbi dbs); int mdb_env_get_maxkeysize (MDB_envp env); int mdb_env_set_userctx (MDB_envp env, void* ctx); void* mdb_env_get_userctx (MDB_envp env); int mdb_env_set_assert (MDB_envp env, void function (MDB_envp env, const(char)* msg) func); int mdb_txn_begin (MDB_envp env, MDB_txnp parent, uint flags, MDB_txnp* txn); MDB_envp mdb_txn_env (MDB_txnp txn); usize mdb_txn_id (MDB_txnp txn); int mdb_txn_commit (MDB_txnp txn); void mdb_txn_abort (MDB_txnp txn); void mdb_txn_reset (MDB_txnp txn); int mdb_txn_renew (MDB_txnp txn); int mdb_dbi_open (MDB_txnp txn, const(char)* name, uint flags, MDB_dbi* dbi); int mdb_stat (MDB_txnp txn, MDB_dbi dbi, MDB_stat* stat); int mdb_dbi_flags (MDB_txnp txn, MDB_dbi dbi, uint* flags); void mdb_dbi_close (MDB_envp env, MDB_dbi dbi); int mdb_drop (MDB_txnp txn, MDB_dbi dbi, int del); int mdb_set_compare (MDB_txnp txn, MDB_dbi dbi, int function (MDB_val* a, MDB_val* b) cmp); int mdb_set_dupsort (MDB_txnp txn, MDB_dbi dbi, int function (MDB_val* a, MDB_val* b) cmp); int mdb_set_relfunc (MDB_txnp txn, MDB_dbi dbi, void function (MDB_val* item, void* oldptr, void* newptr, void* relctx) rel); int mdb_set_relctx (MDB_txnp txn, MDB_dbi dbi, void* ctx); int mdb_get (MDB_txnp txn, MDB_dbi dbi, MDB_val* key, MDB_val* data); int mdb_put (MDB_txnp txn, MDB_dbi dbi, MDB_val* key, MDB_val* data, uint flags); int mdb_del (MDB_txnp txn, MDB_dbi dbi, MDB_val* key, MDB_val* data); int mdb_cursor_open (MDB_txnp txn, MDB_dbi dbi, MDB_cursorp* cursor); void mdb_cursor_close (MDB_cursorp cursor); int mdb_cursor_renew (MDB_txnp txn, MDB_cursorp cursor); MDB_txnp mdb_cursor_txn (MDB_cursorp cursor); MDB_dbi mdb_cursor_dbi (MDB_cursorp cursor); int mdb_cursor_get (MDB_cursorp cursor, MDB_val* key, MDB_val* data, /*MDB_cursor_op*/uint op); int mdb_cursor_put (MDB_cursorp cursor, MDB_val* key, MDB_val* data, uint flags); int mdb_cursor_del (MDB_cursorp cursor, uint flags); int mdb_cursor_count (MDB_cursorp cursor, usize* countp); int mdb_cmp (MDB_txnp txn, MDB_dbi dbi, MDB_val* a, MDB_val* b); int mdb_dcmp (MDB_txnp txn, MDB_dbi dbi, MDB_val* a, MDB_val* b); int mdb_reader_list (MDB_envp env, int function (const(char)* msg, void* ctx) func, void* ctx); int mdb_reader_check (MDB_envp env, int* dead); appstream-generator-0.6.8/src/asgen/bindings/pango.d000066400000000000000000000020121320016272000224230ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.pango; extern(C): nothrow: @nogc: struct PangoLanguage {}; PangoLanguage *pango_language_from_string (const(char) *language); const(char) *pango_language_get_sample_string (PangoLanguage *language); appstream-generator-0.6.8/src/asgen/bindings/rsvg.d000066400000000000000000000026351320016272000223130ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ module asgen.bindings.rsvg; import glib.c.types; import asgen.bindings.cairo; extern(C): nothrow: @nogc: struct _RsvgHandle {} alias RsvgHandle = _RsvgHandle*; struct RsvgDimensionData { int width; int height; double em; double ex; }; RsvgHandle rsvg_handle_new (); void g_object_unref (void* object); bool rsvg_handle_write (RsvgHandle handle, const(ubyte) *buf, long count, GError **error); bool rsvg_handle_close (RsvgHandle handle, GError **error); void rsvg_handle_get_dimensions (RsvgHandle handle, RsvgDimensionData *dimension_data); bool rsvg_handle_render_cairo (RsvgHandle handle, cairo_p cr); appstream-generator-0.6.8/src/asgen/config.d000066400000000000000000000354351320016272000210060ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.config; import std.stdio; import std.array; import std.string : format, toLower; import std.path : dirName, getcwd, buildPath, buildNormalizedPath; import std.conv : to; import std.json; import std.typecons; static import std.file; public import appstream.c.types : FormatVersion; import asgen.utils : existsAndIsDir, randomString; import asgen.logging; import asgen.defines : DATADIR; /** * Describes a suite in a software repository. **/ struct Suite { string name; int dataPriority = 0; string baseSuite; string iconTheme; string[] sections; string[] architectures; bool isImmutable; } /** * The AppStream metadata type we want to generate. **/ enum DataType { XML, YAML } /** * Distribution-specific backends. **/ enum Backend { Unknown, Dummy, Debian, Ubuntu, Archlinux, RpmMd } enum GeneratorFeature { NONE = 0, PROCESS_DESKTOP = 1 << 0, VALIDATE = 1 << 1, NO_DOWNLOADS = 1 << 2, STORE_SCREENSHOTS = 1 << 3, OPTIPNG = 1 << 4, METADATA_TIMESTAMPS = 1 << 5, IMMUTABLE_SUITES = 1 << 6, PROCESS_FONTS = 1 << 7, PROCESS_GSTREAMER = 1 << 8, } final class Config { private: private string workspaceDir; private string exportDir; private string tmpDir; // Thread local private static bool instantiated_; // Thread global private __gshared Config instance_; private this () { formatVersion = FormatVersion.V0_10; } public: FormatVersion formatVersion; string projectName; string archiveRoot; string mediaBaseUrl; string htmlBaseUrl; Backend backend; Suite[] suites; string[] oldsuites; DataType metadataType; uint enabledFeatures; // bitfield bool[string] allowedCustomKeys; // set of allowed keys in tags string dataExportDir; string hintsExportDir; string mediaExportDir; string htmlExportDir; string caInfo; static Config get () { if (!instantiated_) { synchronized (Config.classinfo) { if (!instance_) instance_ = new Config (); instantiated_ = true; } } return instance_; } @property string formatVersionStr () { import asgen.bindings.appstream_utils; import std.string : fromStringz; return fromStringz (as_format_version_to_string (formatVersion)); } @property const string databaseDir () { return buildPath (workspaceDir, "db"); } @property const string cacheRootDir () { return buildPath (workspaceDir, "cache"); } @property string templateDir () { // find a suitable template directory // first check the workspace auto tdir = buildPath (workspaceDir, "templates"); tdir = getVendorTemplateDir (tdir, true); if (tdir is null) { immutable exeDir = dirName (std.file.thisExePath ()); tdir = buildNormalizedPath (exeDir, "..", "data", "templates"); tdir = getVendorTemplateDir (tdir); if (tdir is null) { tdir = getVendorTemplateDir (buildPath (DATADIR, "templates")); } } return tdir; } /** * Helper function to determine a vendor template directory. */ private string getVendorTemplateDir (const string dir, bool allowRoot = false) @safe { string tdir; if (projectName !is null) { tdir = buildPath (dir, projectName.toLower ()); if (existsAndIsDir (tdir)) return tdir; } tdir = buildPath (dir, "default"); if (existsAndIsDir (tdir)) return tdir; if (allowRoot) { if (existsAndIsDir (dir)) return dir; } return null; } private void setFeature (GeneratorFeature feature, bool enabled) { if (enabled) enabledFeatures |= feature; else disableFeature (feature); } private void disableFeature (GeneratorFeature feature) { enabledFeatures &= ~feature; } bool featureEnabled (GeneratorFeature feature) { return (enabledFeatures & feature) > 0; } void loadFromFile (string fname) { // read the configuration JSON file auto f = File (fname, "r"); string jsonData; string line; while ((line = f.readln ()) !is null) jsonData ~= line; JSONValue root = parseJSON (jsonData); workspaceDir = dirName (fname); if (workspaceDir.empty) workspaceDir = getcwd (); this.projectName = "Unknown"; if ("ProjectName" in root) this.projectName = root["ProjectName"].str; this.archiveRoot = root["ArchiveRoot"].str; this.mediaBaseUrl = ""; if ("MediaBaseUrl" in root) this.mediaBaseUrl = root["MediaBaseUrl"].str; this.htmlBaseUrl = ""; if ("HtmlBaseUrl" in root) this.htmlBaseUrl = root["HtmlBaseUrl"].str; // set the default export directory locations, allow people to override them in the config exportDir = buildPath (workspaceDir, "export"); mediaExportDir = buildPath (exportDir, "media"); dataExportDir = buildPath (exportDir, "data"); hintsExportDir = buildPath (exportDir, "hints"); htmlExportDir = buildPath (exportDir, "html"); if ("ExportDirs" in root) { auto edirs = root["ExportDirs"].object; foreach (dirId; edirs.byKeyValue) { switch (dirId.key) { case "Media": mediaExportDir = dirId.value.str; break; case "Data": dataExportDir = dirId.value.str; break; case "Hints": hintsExportDir = dirId.value.str; break; case "Html": htmlExportDir = dirId.value.str; break; default: logWarning ("Unknown export directory specifier in config: %s", dirId.key); } } } this.metadataType = DataType.XML; if ("MetadataType" in root) if (root["MetadataType"].str.toLower () == "yaml") this.metadataType = DataType.YAML; if ("CAInfo" in root) this.caInfo = root["CAInfo"].str; // allow specifying the AppStream format version we build data for. if ("FormatVersion" in root) { immutable versionStr = root["FormatVersion"].str; if (versionStr == "0.8") formatVersion = FormatVersion.V0_8; else if (versionStr == "0.9") formatVersion = FormatVersion.V0_9; else if (versionStr == "0.10") formatVersion = FormatVersion.V0_10; } // we default to the Debian backend for now auto backendName = "debian"; if ("Backend" in root) backendName = root["Backend"].str.toLower (); switch (backendName) { case "dummy": this.backend = Backend.Dummy; this.metadataType = DataType.YAML; break; case "debian": this.backend = Backend.Debian; this.metadataType = DataType.YAML; break; case "ubuntu": this.backend = Backend.Ubuntu; this.metadataType = DataType.YAML; break; case "arch": case "archlinux": this.backend = Backend.Archlinux; this.metadataType = DataType.XML; break; case "mageia": case "rpmmd": this.backend = Backend.RpmMd; this.metadataType = DataType.XML; break; default: break; } auto hasImmutableSuites = false; foreach (suiteName; root["Suites"].object.byKey ()) { Suite suite; suite.name = suiteName; // having a suite named "pool" will result in the media pool being copied on // itself if immutableSuites is used. Since 'pool' is a bad suite name anyway, // we error out early on this. if (suiteName == "pool") throw new Exception ("The name 'pool' is forbidden for a suite."); auto sn = root["Suites"][suiteName]; if ("dataPriority" in sn) suite.dataPriority = to!int (sn["dataPriority"].integer); if ("baseSuite" in sn) suite.baseSuite = sn["baseSuite"].str; if ("useIconTheme" in sn) suite.iconTheme = sn["useIconTheme"].str; if ("sections" in sn) foreach (sec; sn["sections"].array) suite.sections ~= sec.str; if ("architectures" in sn) foreach (arch; sn["architectures"].array) suite.architectures ~= arch.str; if ("immutable" in sn) { suite.isImmutable = sn["immutable"].type == JSON_TYPE.TRUE; if (suite.isImmutable) hasImmutableSuites = true; } suites ~= suite; } if ("Oldsuites" in root.object) { import std.algorithm.iteration : map; oldsuites = map!"a.str"(root["Oldsuites"].array).array; } if ("AllowedCustomKeys" in root.object) foreach (ref key; root["AllowedCustomKeys"].array) allowedCustomKeys[key.str] = true; // Enable features which are default-enabled setFeature (GeneratorFeature.PROCESS_DESKTOP, true); setFeature (GeneratorFeature.VALIDATE, true); setFeature (GeneratorFeature.STORE_SCREENSHOTS, true); setFeature (GeneratorFeature.OPTIPNG, true); setFeature (GeneratorFeature.METADATA_TIMESTAMPS, true); setFeature (GeneratorFeature.IMMUTABLE_SUITES, true); setFeature (GeneratorFeature.PROCESS_FONTS, true); setFeature (GeneratorFeature.PROCESS_GSTREAMER, true); // apply vendor feature settings if ("Features" in root.object) { auto featuresObj = root["Features"].object; foreach (featureId; featuresObj.byKey ()) { switch (featureId) { case "validateMetainfo": setFeature (GeneratorFeature.VALIDATE, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "processDesktop": setFeature (GeneratorFeature.PROCESS_DESKTOP, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "noDownloads": setFeature (GeneratorFeature.NO_DOWNLOADS, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "createScreenshotsStore": setFeature (GeneratorFeature.STORE_SCREENSHOTS, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "optimizePNGSize": setFeature (GeneratorFeature.OPTIPNG, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "metadataTimestamps": setFeature (GeneratorFeature.METADATA_TIMESTAMPS, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "immutableSuites": setFeature (GeneratorFeature.METADATA_TIMESTAMPS, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "processFonts": setFeature (GeneratorFeature.PROCESS_FONTS, featuresObj[featureId].type == JSON_TYPE.TRUE); break; case "processGStreamer": setFeature (GeneratorFeature.PROCESS_GSTREAMER, featuresObj[featureId].type == JSON_TYPE.TRUE); break; default: break; } } } // check if we need to disable features because some prerequisites are not met if (featureEnabled (GeneratorFeature.OPTIPNG)) { if (!std.file.exists ("/usr/bin/optipng")) { setFeature (GeneratorFeature.OPTIPNG, false); logError ("Disabled feature `optimizePNGSize`: The `optipng` binary was not found."); } } if (featureEnabled (GeneratorFeature.NO_DOWNLOADS)) { // since disallowing network access might have quite a lot of sideeffects, we print // a message to the logs to make debugging easier. // in general, running with noDownloads is discouraged. logWarning ("Configuration does not permit downloading files. Several features will not be available."); } if (!featureEnabled (GeneratorFeature.IMMUTABLE_SUITES)) { // Immutable suites won't work if the feature is disabled - log this error if (hasImmutableSuites) logError ("Suites are defined as immutable, but the `immutableSuites` feature is disabled. Immutability will not work!"); } } bool isValid () { return this.projectName != null; } /** * Get unique temporary directory to use during one generator run. */ string getTmpDir () { if (tmpDir.empty) { synchronized (this) { string root; if (cacheRootDir.empty) root = "/tmp/"; else root = cacheRootDir; tmpDir = buildPath (root, "tmp", format ("asgen-%s", randomString (8))); } } return tmpDir; } } appstream-generator-0.6.8/src/asgen/contentsstore.d000066400000000000000000000232471320016272000224510ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.contentsstore; import std.stdio; import std.string; import std.conv : to, octal; import std.file : mkdirRecurse; import std.array : appender, join, split, empty; static import std.math; import asgen.bindings.lmdb; import asgen.config; import asgen.logging; /** * Contains a cache about available files in packages. * This is useful for finding icons and for re-scanning * packages which become interesting later. **/ final class ContentsStore { private: MDB_envp dbEnv; MDB_dbi dbContents; MDB_dbi dbIcons; bool opened; public: this () { opened = false; } ~this () { if (opened) dbEnv.mdb_env_close (); } private void checkError (int rc, string msg) { if (rc != 0) { import std.format; throw new Exception (format ("%s[%s]: %s", msg, rc, mdb_strerror (rc).fromStringz)); } } void open (string dir) { int rc; assert (!opened); logDebug ("Opening contents cache."); // ensure the cache directory exists mkdirRecurse (dir); rc = mdb_env_create (&dbEnv); scope (success) opened = true; scope (failure) dbEnv.mdb_env_close (); checkError (rc, "mdb_env_create"); // We are going to use at max 2 sub-databases: // contents and icons rc = dbEnv.mdb_env_set_maxdbs (2); checkError (rc, "mdb_env_set_maxdbs"); // set a huge map size to be futureproof. // This means we're cruel to non-64bit users, but this // software is supposed to be run on 64bit machines anyway. auto mapsize = cast (size_t) std.math.pow (512L, 4); rc = dbEnv.mdb_env_set_mapsize (mapsize); checkError (rc, "mdb_env_set_mapsize"); // open database rc = dbEnv.mdb_env_open (dir.toStringz (), MDB_NOMETASYNC | MDB_NOTLS, octal!755); checkError (rc, "mdb_env_open"); // open sub-databases in the environment MDB_txnp txn; rc = dbEnv.mdb_txn_begin (null, 0, &txn); checkError (rc, "mdb_txn_begin"); scope (failure) txn.mdb_txn_abort (); // contains a full list of all contents rc = txn.mdb_dbi_open ("contents", MDB_CREATE, &dbContents); checkError (rc, "open contents database"); // contains list of icon files and related data // the contents sub-database exists only to allow building instances // of IconHandler much faster. rc = txn.mdb_dbi_open ("icondata", MDB_CREATE, &dbIcons); checkError (rc, "open icon-info database"); rc = txn.mdb_txn_commit (); checkError (rc, "mdb_txn_commit"); } void open (Config conf) { import std.path : buildPath; this.open (buildPath (conf.databaseDir, "contents")); } private MDB_val makeDbValue (string data) { import core.stdc.string : strlen; MDB_val mval; auto cdata = data.toStringz (); mval.mv_size = char.sizeof * strlen (cdata) + 1; mval.mv_data = cast(void *) cdata; return mval; } private MDB_txnp newTransaction (uint flags = 0) { int rc; MDB_txnp txn; rc = dbEnv.mdb_txn_begin (null, flags, &txn); checkError (rc, "mdb_txn_begin"); return txn; } private void commitTransaction (MDB_txnp txn) { auto rc = txn.mdb_txn_commit (); checkError (rc, "mdb_txn_commit"); } private void quitTransaction (MDB_txnp txn) { if (txn is null) return; txn.mdb_txn_abort (); } /** * Drop a package-id from the contents cache. */ void removePackage (string pkid) { MDB_val key; key = makeDbValue (pkid); auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_del (dbContents, &key, null); checkError (res, "mdb_del (contents)"); res = txn.mdb_del (dbIcons, &key, null); if (res != MDB_NOTFOUND) checkError (res, "mdb_del (icons)"); } bool packageExists (string pkid) { MDB_val dkey; MDB_cursorp cur; dkey = makeDbValue (pkid); auto txn = newTransaction (MDB_RDONLY); scope (exit) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbContents, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open"); res = cur.mdb_cursor_get (&dkey, null, MDB_SET); if (res == MDB_NOTFOUND) return false; checkError (res, "mdb_cursor_get"); return true; } void addContents (string pkid, string[] contents) { MDB_val key; MDB_val contentsVal, iconsVal; // filter out icon filenames and filenames of icon-related stuff (e.g. theme.index) auto iconInfo = appender!(string[]); foreach (ref c; contents) { if ((c.startsWith ("/usr/share/icons/")) || (c.startsWith ("/usr/share/pixmaps/"))) { iconInfo ~= c; } } immutable contentsStr = contents.join ("\n"); key = makeDbValue (pkid); contentsVal = makeDbValue (contentsStr); auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_put (dbContents, &key, &contentsVal, 0); checkError (res, "mdb_put"); if (!iconInfo.data.empty) { // we have icon information, store it too immutable iconsStr = iconInfo.data.join ("\n"); iconsVal = makeDbValue (iconsStr); res = txn.mdb_put (dbIcons, &key, &iconsVal, 0); checkError (res, "mdb_put (icons)"); } } private string[string] getFilesMap (string[] pkids, MDB_dbi dbi) { MDB_cursorp cur; auto txn = newTransaction (MDB_RDONLY); scope (exit) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbi, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open"); string[string] pkgCMap; foreach (ref pkid; pkids) { MDB_val pkey = makeDbValue (pkid); MDB_val cval; res = cur.mdb_cursor_get (&pkey, &cval, MDB_SET); if (res == MDB_NOTFOUND) continue; checkError (res, "mdb_cursor_get"); auto data = fromStringz (cast(char*) cval.mv_data); auto contents = to!string (data); foreach (ref c; contents.split ("\n")) { pkgCMap[c] = pkid; } } return pkgCMap; } string[string] getContentsMap (string[] pkids) { return getFilesMap (pkids, dbContents); } string[string] getIconFilesMap (string[] pkids) { return getFilesMap (pkids, dbIcons); } private string[] getContentsList (string pkid, MDB_dbi dbi) { MDB_val pkey, cval; MDB_cursorp cur; pkey = makeDbValue (pkid); auto txn = newTransaction (MDB_RDONLY); scope (exit) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbi, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open"); res = cur.mdb_cursor_get (&pkey, &cval, MDB_SET); if (res == MDB_NOTFOUND) return null; checkError (res, "mdb_cursor_get"); auto data = fromStringz (cast(char*) cval.mv_data); auto contentsStr = to!string (data); return contentsStr.split ("\n"); } string[] getContents (string pkid) { return getContentsList (pkid, dbContents); } string[] getIcons (string pkid) { return getContentsList (pkid, dbIcons); } void removePackagesNotInSet (bool[string] pkgSet) { MDB_cursorp cur; auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbContents, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open (pkgcruft_contents)"); MDB_val pkey; while (cur.mdb_cursor_get (&pkey, null, MDB_NEXT) == 0) { immutable pkid = to!string (fromStringz (cast(char*) pkey.mv_data)); if (pkid in pkgSet) continue; // if we got here, the package is not in the set of valid packages, // and we can remove it. res = cur.mdb_cursor_del (0); checkError (res, "mdb_del"); res = txn.mdb_del (dbIcons, &pkey, null); if (res != MDB_NOTFOUND) checkError (res, "mdb_del (icons)"); } } void sync () { dbEnv.mdb_env_sync (1); } } appstream-generator-0.6.8/src/asgen/datastore.d000066400000000000000000000530171320016272000215230ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.datastore; import std.stdio; import std.string; import std.conv : to, octal; import std.file : mkdirRecurse; import std.path : buildPath, buildNormalizedPath, pathSplitter; import std.array : appender; import std.typecons : Tuple, scoped; import std.json; static import std.math; import asgen.bindings.lmdb; import appstream.Metadata; import appstream.Component; import asgen.config; import asgen.logging; import asgen.config : DataType; import asgen.result; /** * Main database containing information about scanned packages, * the components they provide, the component metadata itself, * issues found as well as statistics about the metadata evolution * over time. **/ final class DataStore { private: MDB_envp dbEnv; MDB_dbi dbRepoInfo; MDB_dbi dbPackages; MDB_dbi dbDataXml; MDB_dbi dbDataYaml; MDB_dbi dbHints; MDB_dbi dbStats; bool opened; Metadata mdata; string mediaDir; public: struct StatisticsEntry { size_t time; JSONValue data; } this () { opened = false; mdata = new Metadata (); mdata.setLocale ("ALL"); mdata.setFormatVersion (Config.get ().formatVersion); mdata.setWriteHeader(false); } ~this () { if (opened) dbEnv.mdb_env_close (); } @property string mediaExportPoolDir () { return mediaDir; } private void checkError (int rc, string msg) { if (rc != 0) { import std.format; throw new Exception (format ("%s[%s]: %s", msg, rc, mdb_strerror (rc).fromStringz)); } } private void printVersionDbg () { import std.stdio : writeln; int major, minor, patch; auto ver = mdb_version (&major, &minor, &patch); logDebug ("Using %s major=%s minor=%s patch=%s", ver.fromStringz, major, minor, patch); } void open (string dir, string mediaBaseDir) { int rc; assert (opened == false); // add LMDB version we are using to the debug output printVersionDbg (); // ensure the cache directory exists mkdirRecurse (dir); rc = mdb_env_create (&dbEnv); scope (success) opened = true; scope (failure) dbEnv.mdb_env_close (); checkError (rc, "mdb_env_create"); // We are going to use at max 6 sub-databases: // packages, hints, metadata_xml, metadata_yaml, statistics rc = dbEnv.mdb_env_set_maxdbs (6); checkError (rc, "mdb_env_set_maxdbs"); // set a huge map size to be futureproof. // This means we're cruel to non-64bit users, but this // software is supposed to be run on 64bit machines anyway. auto mapsize = cast (size_t) std.math.pow (512L, 4); rc = dbEnv.mdb_env_set_mapsize (mapsize); checkError (rc, "mdb_env_set_mapsize"); // open database rc = dbEnv.mdb_env_open (dir.toStringz (), MDB_NOMETASYNC | MDB_NOTLS, octal!755); checkError (rc, "mdb_env_open"); // open sub-databases in the environment MDB_txnp txn; rc = dbEnv.mdb_txn_begin (null, 0, &txn); checkError (rc, "mdb_txn_begin"); scope (failure) txn.mdb_txn_abort (); rc = txn.mdb_dbi_open ("packages", MDB_CREATE, &dbPackages); checkError (rc, "open packages database"); rc = txn.mdb_dbi_open ("repository", MDB_CREATE, &dbRepoInfo); checkError (rc, "open repository database"); rc = txn.mdb_dbi_open ("metadata_xml", MDB_CREATE, &dbDataXml); checkError (rc, "open metadata (xml) database"); rc = txn.mdb_dbi_open ("metadata_yaml", MDB_CREATE, &dbDataYaml); checkError (rc, "open metadata (yaml) database"); rc = txn.mdb_dbi_open ("hints", MDB_CREATE, &dbHints); checkError (rc, "open hints database"); rc = txn.mdb_dbi_open ("statistics", MDB_CREATE | MDB_INTEGERKEY, &dbStats); checkError (rc, "open statistics database"); rc = txn.mdb_txn_commit (); checkError (rc, "mdb_txn_commit"); this.mediaDir = buildPath (mediaBaseDir, "pool"); mkdirRecurse (this.mediaDir); } void open (Config conf) { this.open (buildPath (conf.databaseDir, "main"), conf.mediaExportDir); } private MDB_val makeDbValue (string data) { import core.stdc.string : strlen; MDB_val mval; auto cdata = data.toStringz (); mval.mv_size = char.sizeof * strlen (cdata) + 1; mval.mv_data = cast(void *) cdata; return mval; } private MDB_txnp newTransaction (uint flags = 0) { int rc; MDB_txnp txn; rc = dbEnv.mdb_txn_begin (null, flags, &txn); checkError (rc, "mdb_txn_begin"); return txn; } private void commitTransaction (MDB_txnp txn) { auto rc = txn.mdb_txn_commit (); checkError (rc, "mdb_txn_commit"); } private void quitTransaction (MDB_txnp txn) { if (txn is null) return; txn.mdb_txn_abort (); } private void putKeyValue (MDB_dbi dbi, string key, string value) { MDB_val dbkey, dbvalue; dbkey = makeDbValue (key); dbvalue = makeDbValue (value); auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_put (dbi, &dbkey, &dbvalue, 0); checkError (res, "mdb_put"); } private string getValue (MDB_dbi dbi, MDB_val dkey) { import std.conv; MDB_val dval; MDB_cursorp cur; auto txn = newTransaction (MDB_RDONLY); scope (exit) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbi, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open"); res = cur.mdb_cursor_get (&dkey, &dval, MDB_SET); if (res == MDB_NOTFOUND) return null; checkError (res, "mdb_cursor_get"); auto data = fromStringz (cast(char*) dval.mv_data); return to!string (data); } private string getValue (MDB_dbi dbi, string key) { MDB_val dkey; dkey = makeDbValue (key); return getValue (dbi, dkey); } bool metadataExists (DataType dtype, string gcid) { return getMetadata (dtype, gcid) !is null; } void setMetadata (DataType dtype, string gcid, string asdata) { if (dtype == DataType.XML) putKeyValue (dbDataXml, gcid, asdata); else putKeyValue (dbDataYaml, gcid, asdata); } string getMetadata (DataType dtype, string gcid) { string data; if (dtype == DataType.XML) data = getValue (dbDataXml, gcid); else data = getValue (dbDataYaml, gcid); return data; } bool hasHints (string pkid) { return getValue (dbHints, pkid) !is null; } void setHints (string pkid, string hintsYaml) { putKeyValue (dbHints, pkid, hintsYaml); } string getHints (string pkid) { return getValue (dbHints, pkid); } string getPackageValue (string pkid) { return getValue (dbPackages, pkid); } void setPackageIgnore (string pkid) { putKeyValue (dbPackages, pkid, "ignore"); } bool isIgnored (string pkid) { auto val = getValue (dbPackages, pkid); return val == "ignore"; } bool packageExists (string pkid) { auto val = getValue (dbPackages, pkid); return val !is null; } void addGeneratorResult (DataType dtype, GeneratorResult gres) { // if the package has no components or hints, // mark it as always-ignore if (gres.packageIsIgnored ()) { setPackageIgnore (gres.pkid); return; } foreach (ref cpt; gres.getComponents ()) { auto gcid = gres.gcidForComponent (cpt); if (metadataExists (dtype, gcid)) { // we already have seen this exact metadata - only adjust the reference, // and don't regenerate it. continue; } mdata.clearComponents (); mdata.addComponent (cpt); // convert out compoent into metadata string data; try { if (dtype == DataType.XML) { data = mdata.componentsToCollection (FormatKind.XML); } else { data = mdata.componentsToCollection (FormatKind.YAML); } } catch (Exception e) { gres.addHint (cpt.getId (), "metadata-serialization-failed", e.msg); continue; } // remove trailing whitespaces and linebreaks data = data.stripRight (); // store metadata if (!empty (data)) setMetadata (dtype, gcid, data); } if (gres.hintsCount () > 0) { auto hintsJson = gres.hintsToJson (); if (!hintsJson.empty) setHints (gres.pkid, hintsJson); } auto gcids = gres.getGCIDs (); if (gcids.empty) { // no global components, and we're not ignoring this component. // this means we likely have hints stored for this one. Mark it // as "seen" so we don't reprocess it again. putKeyValue (dbPackages, gres.pkid, "seen"); } else { import std.array : join; // store global component IDs for this package as newline-separated list auto gcidVal = join (gcids, "\n"); putKeyValue (dbPackages, gres.pkid, gcidVal); } } string[] getGCIDsForPackage (string pkid) { auto pkval = getPackageValue (pkid); if (pkval == "ignore") return null; if (pkval == "seen") return null; auto validCids = appender!(string[]); auto cids = pkval.split ("\n"); foreach (cid; cids) { if (cid.empty) continue; validCids ~= cid; } return validCids.data; } string[] getMetadataForPackage (DataType dtype, string pkid) { auto gcids = getGCIDsForPackage (pkid); if (gcids is null) return null; auto res = appender!(string[]); foreach (cid; gcids) { auto data = getMetadata (dtype, cid); if (!data.empty) res ~= data; } return res.data; } /** * Drop a package from the database. This process might leave cruft behind, * which can be collected using the cleanupCruft() method. */ void removePackage (string pkid) { MDB_val dbkey; dbkey = makeDbValue (pkid); auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_del (dbPackages, &dbkey, null); if (res != MDB_NOTFOUND) checkError (res, "mdb_del"); res = txn.mdb_del (dbHints, &dbkey, null); if (res != MDB_NOTFOUND) checkError (res, "mdb_del"); } private auto getActiveGCIDs () { MDB_val dkey, dval; MDB_cursorp cur; string[long] stats; auto txn = newTransaction (MDB_RDONLY); scope (exit) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbPackages, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open (gcids)"); bool[string] gcids; while (cur.mdb_cursor_get (&dkey, &dval, MDB_NEXT) == 0) { auto pkval = to!string (fromStringz (cast(char*) dval.mv_data)); if ((pkval == "ignore") || (pkval == "seen")) continue; foreach (gcid; pkval.split ("\n")) gcids[gcid] = true; } return gcids; } void cleanupCruft () { import std.file; import std.array : array; if (mediaDir is null) { logError ("Can not clean up cruft: No media directory is set."); return; } auto activeGCIDs = getActiveGCIDs (); bool gcidReferenced (string gcid) { // we use an associative array as a set here return (gcid in activeGCIDs) !is null; } void dropOrphanedData (MDB_dbi dbi) { MDB_cursorp cur; auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbi, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open (stats)"); MDB_val ckey; while (cur.mdb_cursor_get (&ckey, null, MDB_NEXT) == 0) { immutable gcid = to!string (fromStringz (cast(char*) ckey.mv_data)); if (gcidReferenced (gcid)) continue; // if we got here, the component is cruft and can be removed res = cur.mdb_cursor_del (0); checkError (res, "mdb_del"); logInfo ("Marked %s as cruft.", gcid); } } bool dirEmpty (string dir) { bool empty = true; foreach (ref e; dirEntries (dir, SpanMode.shallow, false)) { empty = false; break; } return empty; } void cleanupDirs (string rootPath) { auto pdir = buildNormalizedPath (rootPath, ".."); if (!std.file.exists (pdir)) return; if (dirEmpty (pdir)) rmdir (pdir); pdir = buildNormalizedPath (pdir, ".."); if (dirEmpty (pdir)) rmdir (pdir); } // drop orphaned metadata dropOrphanedData (dbDataXml); dropOrphanedData (dbDataYaml); // we need the global Config instance here auto conf = Config.get (); auto mdirLen = mediaDir.length; foreach (ref path; dirEntries (mediaDir, SpanMode.depth, false)) { if (path.length <= mdirLen) continue; immutable relPath = path[mdirLen+1..$]; auto split = array (pathSplitter (relPath)); if (split.length != 4) continue; immutable gcid = relPath; if (gcidReferenced (gcid)) continue; // if we are here, the component is removed and we can drop its media if (std.file.exists (path)) rmdirRecurse (path); // remove possibly empty directories cleanupDirs (path); // expire data in suite-specific media directories, // if suite is not marked as immutable if (conf.featureEnabled (GeneratorFeature.IMMUTABLE_SUITES)) { foreach (ref suite; conf.suites) { if (suite.isImmutable) continue; immutable suiteGCIDMediaDir = buildNormalizedPath (mediaDir, "..", suite.name, gcid); if (std.file.exists (suiteGCIDMediaDir)) rmdirRecurse (suiteGCIDMediaDir); // remove possibly empty directories cleanupDirs (suiteGCIDMediaDir); } } logInfo ("Expired media for '%s'", gcid); } } void removePackagesNotInSet (bool[string] pkgSet) { MDB_cursorp cur; auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbPackages, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open (pkgcruft)"); MDB_val pkey; while (cur.mdb_cursor_get (&pkey, null, MDB_NEXT) == 0) { immutable pkid = to!string (fromStringz (cast(char*) pkey.mv_data)); if (pkid in pkgSet) continue; // if we got here, the package is not in the set of valid packages, // and we can remove it. res = cur.mdb_cursor_del (0); checkError (res, "mdb_del"); logInfo ("Dropped package %s", pkid); } } StatisticsEntry[] getStatistics () { MDB_val dkey, dval; MDB_cursorp cur; auto txn = newTransaction (MDB_RDONLY); scope (exit) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbStats, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open (stats)"); auto stats = appender!(StatisticsEntry[]); while (cur.mdb_cursor_get (&dkey, &dval, MDB_NEXT) == 0) { auto jsonData = to!string (fromStringz (cast(char*) dval.mv_data)); auto timestamp = *(cast(size_t*) dkey.mv_data); auto sentry = StatisticsEntry (timestamp, parseJSON (jsonData)); stats ~= sentry; } return stats.data; } void removeStatistics (size_t time) { MDB_val dbkey; dbkey.mv_size = size_t.sizeof; dbkey.mv_data = &time; auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_del (dbStats, &dbkey, null); if (res != MDB_NOTFOUND) checkError (res, "mdb_del"); } void addStatistics (JSONValue stats) { import core.stdc.time : time; MDB_val dbkey, dbvalue; size_t unixTime = time (null); auto statsJsonStr = stats.toString (); dbkey.mv_size = size_t.sizeof; dbkey.mv_data = &unixTime; dbvalue = makeDbValue (statsJsonStr); auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_put (dbStats, &dbkey, &dbvalue, MDB_APPEND); if (res == MDB_KEYEXIST) { // this point in time already exists, so we need to extend it with additional data // retrieve the old statistics data auto existingJsonData = getValue (dbStats, dbkey); auto existingJson = parseJSON (existingJsonData); // make the new JSON a list of the old and the new data, if it isn't one already JSONValue newJson; if (existingJson.type == JSON_TYPE.ARRAY) { newJson = existingJson; newJson.array ~= stats; } else { newJson = JSONValue ([existingJson, stats]); } // build new database value and add it to the db, overriding the old one statsJsonStr = newJson.toJSON (); dbvalue = makeDbValue (statsJsonStr); res = txn.mdb_put (dbStats, &dbkey, &dbvalue, 0); } checkError (res, "mdb_put (stats)"); } JSONValue getRepoInfo (string suite, string section, string arch) { auto repoid = "%s-%s-%s".format (suite, section, arch); auto jsonData = getValue (dbRepoInfo, repoid); if (jsonData is null) { JSONValue[string] dummy; return JSONValue (dummy); } return parseJSON (jsonData); } void setRepoInfo (string suite, string section, string arch, JSONValue repoInfo) { auto repoid = "%s-%s-%s".format (suite, section, arch); auto jsonData = repoInfo.toJSON (); putKeyValue (dbRepoInfo, repoid, jsonData); } void removeRepoInfo (string suite, string section, string arch) { auto repoid = "%s-%s-%s".format (suite, section, arch); auto dbkey = makeDbValue (repoid); auto txn = newTransaction (); scope (success) commitTransaction (txn); scope (failure) quitTransaction (txn); auto res = txn.mdb_del (dbRepoInfo, &dbkey, null); if (res != MDB_NOTFOUND) checkError (res, "mdb_del"); } /** * Get a list of package-ids which match a prefix. */ string[] getPkidsMatching (string prefix) { MDB_val dkey; MDB_cursorp cur; string[long] stats; auto txn = newTransaction (MDB_RDONLY); scope (exit) quitTransaction (txn); auto res = txn.mdb_cursor_open (dbPackages, &cur); scope (exit) cur.mdb_cursor_close (); checkError (res, "mdb_cursor_open (pkid-match)"); auto pkids = appender!(string[]); prefix ~= "/"; while (cur.mdb_cursor_get (&dkey, null, MDB_NEXT) == 0) { auto pkid = to!string (fromStringz (cast(char*) dkey.mv_data)); if (pkid.startsWith (prefix)) pkids ~= pkid; } return pkids.data; } } appstream-generator-0.6.8/src/asgen/defines.d.in000066400000000000000000000017121320016272000215520ustar00rootroot00000000000000/* * Copyright (C) 2017 Canonical Ltd * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.defines; @safe: // location of arch-indep data for asgen public enum DATADIR = "@datadir@"; // current version of the tool public enum ASGEN_VERSION = "@asgen_version@"; appstream-generator-0.6.8/src/asgen/engine.d000066400000000000000000000734551320016272000210120ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.engine; import std.parallelism : parallel; import std.string : format, count, toLower, startsWith; import std.array : Appender, appender, empty; import std.path : buildPath, buildNormalizedPath; import std.file : mkdirRecurse, rmdirRecurse; import std.algorithm : canFind, sort, SwapStrategy; import std.typecons : scoped, Nullable, Tuple; static import std.file; import appstream.Component; import asgen.config; import asgen.logging; import asgen.extractor; import asgen.datastore; import asgen.contentsstore; import asgen.result; import asgen.hint; import asgen.reportgenerator; import asgen.utils : copyDir, stringArrayToByteArray; import asgen.backends.interfaces; import asgen.backends.dummy; import asgen.backends.debian; import asgen.backends.ubuntu; import asgen.backends.archlinux; import asgen.backends.rpmmd; import asgen.handlers.iconhandler; final class Engine { private: Config conf; PackageIndex pkgIndex; DataStore dstore; ContentsStore cstore; bool m_forced; public: this () { this.conf = Config.get (); switch (conf.backend) { case Backend.Dummy: pkgIndex = new DummyPackageIndex (conf.archiveRoot); break; case Backend.Debian: pkgIndex = new DebianPackageIndex (conf.archiveRoot); break; case Backend.Ubuntu: pkgIndex = new UbuntuPackageIndex (conf.archiveRoot); break; case Backend.Archlinux: pkgIndex = new ArchPackageIndex (conf.archiveRoot); break; case Backend.RpmMd: pkgIndex = new RPMPackageIndex (conf.archiveRoot); break; default: throw new Exception ("No backend specified, can not continue!"); } // create cache in cache directory on workspace dstore = new DataStore (); dstore.open (conf); // open package contents cache cstore = new ContentsStore (); cstore.open (conf); // for Cairo/Fontconfig issues with multithreading import asgen.image : setupFontconfigMutex; if (conf.featureEnabled (GeneratorFeature.PROCESS_FONTS)) setupFontconfigMutex (); } @property bool forced () { return m_forced; } @property void forced (bool v) { m_forced = v; } private void gcCollect () { static import core.memory; logDebug ("Minimize GC collection cycle triggered explicitly."); core.memory.GC.collect (); core.memory.GC.minimize (); } /** * Extract metadata from a software container (usually a distro package). * The result is automatically stored in the database. */ private void processPackages (Package[] pkgs, IconHandler iconh) { auto mde = scoped!DataExtractor (dstore, iconh); foreach (ref pkg; parallel (pkgs)) { immutable pkid = pkg.id; if (dstore.packageExists (pkid)) continue; auto res = mde.processPackage (pkg); synchronized (dstore) { // write resulting data into the database dstore.addGeneratorResult (this.conf.metadataType, res); logInfo ("Processed %s, components: %s, hints: %s", res.pkid, res.componentsCount (), res.hintsCount ()); } // we don't need this package anymore pkg.close (); } } /** * Populate the contents index with new contents data. While we are at it, we can also mark * some uninteresting packages as to-be-ignored, so we don't waste time on them * during the following metadata extraction. * * Returns: True in case we have new interesting packages, false otherwise. **/ private bool seedContentsData (Suite suite, string section, string arch) { bool packageInteresting (Package pkg) { auto contents = pkg.contents; foreach (ref c; contents) { if (c.startsWith ("/usr/share/applications/")) return true; if (c.startsWith ("/usr/share/metainfo/")) return true; if (c.startsWith ("/usr/share/appdata/")) return true; } return pkg.gst.isNotEmpty; } // check if the index has changed data, skip the update if there's nothing new if ((!pkgIndex.hasChanges (dstore, suite.name, section, arch)) && (!this.forced)) { logDebug ("Skipping contents cache update for %s/%s [%s], index has not changed.", suite.name, section, arch); return false; } logInfo ("Scanning new packages for %s/%s [%s]", suite.name, section, arch); // get contents information for packages and add them to the database auto interestingFound = false; // First get the contents (only) of all packages in the base suite if (!suite.baseSuite.empty) { logInfo ("Scanning new packages for base suite %s/%s [%s]", suite.baseSuite, section, arch); auto baseSuitePkgs = pkgIndex.packagesFor (suite.baseSuite, section, arch); foreach (ref pkg; parallel (baseSuitePkgs, 8)) { immutable pkid = pkg.id; if (!cstore.packageExists (pkid)) { cstore.addContents (pkid, pkg.contents); logInfo ("Scanned %s for base suite.", pkid); } } } // And then scan the suite itself - here packages can be 'interesting' // in that they might end up in the output. auto pkgs = pkgIndex.packagesFor (suite.name, section, arch); foreach (ref pkg; parallel (pkgs, 8)) { immutable pkid = pkg.id; string[] contents; if (cstore.packageExists (pkid)) { if (dstore.packageExists (pkid)) { // TODO: Unfortunately, packages can move between suites without changing their ID. // This means as soon as we have an interesting package, even if we already processed it, // we need to regenerate the output metadata. // For that to happen, we set interestingFound to true here. Later, a more elegent solution // would be desirable here, ideally one which doesn't force us to track which package is // in which suite as well. if (!dstore.isIgnored (pkid)) interestingFound = true; continue; } // we will complement the main database with ignore data, in case it // went missing. contents = cstore.getContents (pkid); } else { // add contents to the index contents = pkg.contents; cstore.addContents (pkid, contents); } // check if we can already mark this package as ignored, and print some log messages if (!packageInteresting (pkg)) { dstore.setPackageIgnore (pkid); logInfo ("Scanned %s, no interesting files found.", pkid); // we won't use this anymore pkg.close (); } else { logInfo ("Scanned %s, could be interesting.", pkid); interestingFound = true; } } // ensure the contents store is in a consistent state on disk, // since it might be accessed from other threads after this function // is run. cstore.sync (); return interestingFound; } private string getMetadataHead (Suite suite, string section) { import std.datetime : Clock; import core.time : Duration; string head; immutable origin = "%s-%s-%s".format (conf.projectName.toLower, suite.name.toLower, section.toLower); auto time = Clock.currTime (); time.fracSecs = Duration.zero; // we don't want fractional seconds immutable timeStr = time.toISOString (); string mediaPoolUrl = buildPath (conf.mediaBaseUrl, "pool"); if (conf.featureEnabled (GeneratorFeature.IMMUTABLE_SUITES)) { mediaPoolUrl = buildPath (conf.mediaBaseUrl, suite.name); } if (conf.metadataType == DataType.XML) { head = "\n"; head ~= format ("//"); return false; } immutable pkid = identifier; writeln ("== ", pkid, " =="); writeln ("Contents:"); auto pkgContents = cstore.getContents (pkid); if (pkgContents.empty) { writeln ("~ No contents found."); } else { foreach (ref s; pkgContents) writeln (" ", s); } writeln (); writeln ("Icons:"); auto pkgIcons = cstore.getIcons (pkid); if (pkgIcons.empty) { writeln ("~ No icons found."); } else { foreach (ref s; pkgIcons) writeln (" ", s); } writeln (); if (dstore.isIgnored (pkid)) { writeln ("Ignored: yes"); writeln (); } else { writeln ("Global Component IDs:"); foreach (ref s; dstore.getGCIDsForPackage (pkid)) writeln ("- ", s); writeln (); writeln ("Generated Data:"); foreach (ref s; dstore.getMetadataForPackage (conf.metadataType, pkid)) writeln (s); writeln (); } if (dstore.hasHints (pkid)) { writeln ("Hints:"); writeln (dstore.getHints (pkid)); } else { writeln ("Hints: None"); } writeln (); return true; } } // End of Engine class appstream-generator-0.6.8/src/asgen/extractor.d000066400000000000000000000276211320016272000215520ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.extractor; import std.array : appender; import std.stdio; import std.string; import std.path : baseName; import std.algorithm : canFind; import std.typecons : scoped; import appstream.Component; import appstream.Metadata; import asgen.config; import asgen.hint; import asgen.result; import asgen.backends.interfaces; import asgen.datastore; import asgen.handlers; import asgen.utils : componentGetStockIcon; final class DataExtractor { private: Component[] cpts; GeneratorHint[] hints; DataStore dstore; IconHandler iconh; Config conf; DataType dtype; public: this (DataStore db, IconHandler iconHandler) { dstore = db; iconh = iconHandler; conf = Config.get (); dtype = conf.metadataType; } GeneratorResult processPackage (Package pkg) { // create a new result container auto gres = new GeneratorResult (pkg); // prepare a list of metadata files which interest us string[string] desktopFiles; string[] metadataFiles; foreach (ref fname; pkg.contents) { if ((fname.startsWith ("/usr/share/applications")) && (fname.endsWith (".desktop"))) { desktopFiles[baseName (fname)] = fname; continue; } if ((fname.startsWith ("/usr/share/metainfo/")) && (fname.endsWith (".xml"))) { metadataFiles ~= fname; continue; } if ((fname.startsWith ("/usr/share/appdata/")) && (fname.endsWith (".xml"))) { metadataFiles ~= fname; continue; } } // create new AppStream metadata parser auto mdata = scoped!Metadata (); mdata.setLocale ("ALL"); mdata.setFormatStyle (FormatStyle.METAINFO); // now process metainfo XML files foreach (ref mfname; metadataFiles) { auto dataBytes = pkg.getFileData (mfname); auto data = cast(string) dataBytes; mdata.clearComponents (); auto cpt = parseMetaInfoFile (mdata, gres, data, mfname); if (cpt is null) continue; // get component ID (it must exist and not be empty, as validated by the metainfo parser) auto cid = cpt.getId; // check for legacy path if (mfname.startsWith ("/usr/share/appdata/")) { gres.addHint (null, "legacy-metainfo-directory", ["fname": mfname.baseName]); } // we need to add the version to re-download screenshot on every new upload. // otherwise, screenshots would only get updated if the actual metadata file was touched. gres.updateComponentGCID (cpt, pkg.ver); // validate the desktop-id launchables and merge the desktop file data // in case we find it. auto launch = cpt.getLaunchable (LaunchableKind.DESKTOP_ID); if (launch !is null) { auto entries = launch.getEntries (); for (uint i = 0; i < entries.len; i++) { import std.string : fromStringz; import std.conv : to; auto desktopId = (cast(char*) entries.index (i)).fromStringz; auto dfP = desktopId in desktopFiles; if (dfP is null) { gres.addHint (cpt, "missing-launchable-desktop-file", ["desktop_id": desktopId.to!string]); } else if (i == 0) { // always only try to merge in the first .desktop-ID, because if there are multiple // launchables defined, the component *must* not depend on the data in one // single .desktop file anyway. // update component with .desktop file data, ignoring NoDisplay field auto ddataBytes = pkg.getFileData (*dfP); auto ddata = cast(string) ddataBytes; parseDesktopFile (gres, *dfP, ddata, true); // update GCID checksum gres.updateComponentGCID (cpt, ddata); // drop the .desktop file from the list, it has been handled desktopFiles.remove (cid); } } } // For compatibility, we try other methods than using the "launchable" // tag to merge in .desktop files, but only if we actually need to do that. // At the moment we determine whether a .desktop file is needed by checking // if the metainfo file defines an icon (which is commonly provided by the .desktop // file instead of the metainfo file). // This heuristic is, of course, not ideal, which is why everything should have a launchable tag. if ((cpt.getKind == ComponentKind.DESKTOP_APP) && (componentGetStockIcon (cpt).isNull)) { auto dfP = cid in desktopFiles; if (dfP is null) dfP = (cid ~ ".desktop") in desktopFiles; if (dfP is null) { // no .desktop file was found and this component does not // define an icon - this means that a .desktop file is required // and can not be omitted, so we stop processing here. // Otherwise we take the data and see how far we get. // finalize GCID checksum and continue gres.updateComponentGCID (cpt, data); gres.addHint (cpt, "missing-desktop-file"); // we have a desktop-application component, but no .desktop file. // This is an error we can not recover from. continue; } else { // update component with .desktop file data, ignoring NoDisplay field auto ddataBytes = pkg.getFileData (*dfP); auto ddata = cast(string) ddataBytes; parseDesktopFile (gres, *dfP, ddata, true); // update GCID checksum gres.updateComponentGCID (cpt, ddata); // drop the .desktop file from the list, it has been handled desktopFiles.remove (cid); } } // do a validation of the file. Validation is slow, so we allow // the user to disable this feature. if (conf.featureEnabled (GeneratorFeature.VALIDATE)) { if (!dstore.metadataExists (dtype, gres.gcidForComponent (cpt))) validateMetaInfoFile (gres, cpt, data); } } // process the remaining .desktop files foreach (ref dfname; desktopFiles.byValue ()) { auto ddataBytes = pkg.getFileData (dfname); auto ddata = cast(string) ddataBytes; auto cpt = parseDesktopFile (gres, dfname, ddata, false); if (cpt !is null) gres.updateComponentGCID (cpt, ddata); } if (conf.featureEnabled (GeneratorFeature.PROCESS_GSTREAMER) && pkg.gst.isNotEmpty) { auto data = appender!string; auto cpt = new Component (); data.reserve(512); cpt.setId (pkg.name); cpt.setKind (ComponentKind.CODEC); cpt.setName ("GStreamer Multimedia Codecs", "C"); foreach (ref lang, ref desc; pkg.summary) { cpt.setSummary (desc, lang); data ~= desc; } gres.addComponent (cpt); gres.updateComponentGCID (cpt, data.data); } auto hasFontComponent = false; foreach (ref cpt; gres.getComponents ()) { auto gcid = gres.gcidForComponent (cpt); // don't run expensive operations if the metadata already exists auto existingMData = dstore.getMetadata (dtype, gcid); if (existingMData !is null) { // To account for packages which change their package name, we // also need to check if the package this component is associated // with matches ours. // If it doesn't, we can't just link the package to the component. bool samePkg = false; if (dtype == DataType.YAML) { if (existingMData.canFind (format ("Package: %s\n", pkg.name))) samePkg = true; } else { if (existingMData.canFind (format ("%s", pkg.name))) samePkg = true; } if ((!samePkg) && (cpt.getKind != ComponentKind.WEB_APP)) { // The exact same metadata exists in a different package already, we emit an error hint. // ATTENTION: This does not cover the case where *different* metadata (as in, different summary etc.) // but with the *same ID* exists. // We only catch that kind of problem later. auto cdata = new Metadata (); cdata.setFormatStyle (FormatStyle.COLLECTION); cdata.setFormatVersion (conf.formatVersion); if (dtype == DataType.YAML) cdata.parse (existingMData, FormatKind.YAML); else cdata.parse (existingMData, FormatKind.XML); auto ecpt = cdata.getComponent (); const pkgNames = ecpt.getPkgnames; string pkgName = "(none)"; if (!pkgNames.empty) pkgName = pkgNames[0]; gres.addHint (cpt, "metainfo-duplicate-id", ["cid": cpt.getId (), "pkgname": pkgName]); } continue; } // find & store icons iconh.process (gres, cpt); if (gres.isIgnored (cpt)) continue; // download and resize screenshots. // we don't even need to call this if no downloads are allowed. if (!conf.featureEnabled (GeneratorFeature.NO_DOWNLOADS)) processScreenshots (gres, cpt, dstore.mediaExportPoolDir); // we don't want to run expensive font processing if we don't have a font component. // since the font handler needs to load all font data prior to processing the component, // for efficiency we only record whether we need to process fonts here and then handle // them at a later step. // This improves performance for a package that contains multiple font components. if (cpt.getKind () == ComponentKind.FONT) hasFontComponent = true; } // render font previews and extract font metadata (if any of the components is a font) if (conf.featureEnabled (GeneratorFeature.PROCESS_FONTS)) { if (hasFontComponent) processFontData (gres, dstore.mediaExportPoolDir); } // this removes invalid components and cleans up the result gres.finalize (); pkg.close (); return gres; } } appstream-generator-0.6.8/src/asgen/font.d000066400000000000000000000325651320016272000205100ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.font; import std.string : format, fromStringz, toStringz, toLower, strip; import std.conv : to; import std.path : buildPath, baseName; import std.array : empty, appender, replace; import std.algorithm : countUntil, remove; static import std.file; import asgen.bindings.freetype; import asgen.bindings.fontconfig; import asgen.bindings.pango; import asgen.logging; import asgen.config : Config; // NOTE: The font's full-name (and the family-style combo we use if the full name is unavailable), can be // determined on the command-line via: // fc-query --format='FN: %{fullname}\nFS: %{family[0]} %{style[0]}\n' private static __gshared string[string] iconTexts; // initialize module static data shared static this () { if (iconTexts.length != 0) return; synchronized iconTexts = ["en": "Aa", "ar": "أب", "as": "অআই", "bn": "অআই", "be": "Аа", "bg": "Аа", "cs": "Aa", "da": "Aa", "de": "Aa", "es": "Aa", "fr": "Aa", "gu": "અબક", "hi": "अआइ", "he": "אב", "it": "Aa", "kn": "ಅಆಇ", "ml": "ആഇ", "ne": "अआइ", "nl": "Aa", "or": "ଅଆଇ", "pa": "ਅਆਇ", "pl": "ĄĘ", "pt": "Aa", "ru": "Аа", "sv": "Åäö", "ta": "அஆஇ", "te": "అఆఇ", "ua": "Аа", "zh-tw": "漢"]; } final class Font { private: FT_Library library; FT_Face fface; string[] languages_; string sampleText_; string sampleIconText_; string style_; string fullname_; immutable string fileBaseName; public: this (string fname) { // NOTE: Freetype is completely non-threadsafe, but we only use it in the constructor. // So mark this section of code as synchronized to never run it in parallel (even having // two Font objects constructed in parallel may lead to errors) synchronized { initFreeType (); FT_Error err; err = FT_New_Face (library, fname.toStringz (), 0, &fface); if (err != 0) throw new Exception ("Unable to load font face from file. Error code: %s".format (err)); loadFontConfigData (fname); fileBaseName = fname.baseName; } } this (const(ubyte)[] data, string fileBaseName) { import std.stdio : File; // we unfortunately need to create a stupid temporary file here, otherwise Fontconfig // does not work and we can not determine the right demo strings for this font. // (FreeType itself could load from memory) immutable tmpRoot = Config.get ().getTmpDir; std.file.mkdirRecurse (tmpRoot); immutable fname = buildPath (tmpRoot, fileBaseName); auto f = File (fname, "w"); f.rawWrite (data); f.close (); this (fname); } ~this () { release (); } void release () { if (fface !is null) FT_Done_Face (fface); if (library !is null) FT_Done_Library (library); fface = null; library = null; } private bool ready () const { return fface !is null && library !is null; } private void initFreeType () { library = null; fface = null; FT_Error err; err = FT_Init_FreeType (&library); if (err != 0) throw new Exception ("Unable to load FreeType. Error code: %s".format (err)); } private void loadFontConfigData (string fname) { // open FC font patter // the count pointer has to be valid, otherwise FcFreeTypeQuery() crashes. int c; auto fpattern = FcFreeTypeQuery (fname.toStringz, 0, null, &c); scope (exit) FcPatternDestroy (fpattern); // load information about the font auto res = appender!(string[]); auto anyLangAdded = false; auto match = true; for (uint i = 0; match == true; i++) { FcLangSet *ls; match = false; if (FcPatternGetLangSet (fpattern, FC_LANG, i, &ls) == FcResult.Match) { match = true; auto langs = FcLangSetGetLangs (ls); auto list = FcStrListCreate (langs); scope (exit) { FcStrListDone (list); FcStrSetDestroy (langs); } char *tmp; FcStrListFirst (list); while ((tmp = FcStrListNext (list)) !is null) { res ~= to!string (tmp.fromStringz); anyLangAdded = true; } } } char *fullNameVal; if (FcPatternGetString (fpattern, FC_FULLNAME, 0, &fullNameVal) == FcResult.Match) { fullname_ = fullNameVal.fromStringz.dup; } char *styleVal; if (FcPatternGetString (fpattern, FC_STYLE, 0, &styleVal) == FcResult.Match) { style_ = styleVal.fromStringz.dup; } // assume 'en' is available if (!anyLangAdded) res ~= "en"; languages_ = res.data; // prefer the English language if possible // this is a hack since some people don't set their // tag properly. immutable enIndex = languages_.countUntil ("en"); if (anyLangAdded && enIndex > 0) { languages_ = languages_.remove (enIndex); languages_ = "en" ~ languages_; } } @property string family () { assert (ready ()); return to!string (fface.family_name.fromStringz); } @property string style () { return style_; } @property string fullName () { if (fullname_.empty) return "%s %s".format (family, style); else return fullname_; } @property string id () { import std.string; if (this.family is null) return fileBaseName; if (this.style is null) return fileBaseName; return "%s-%s".format (this.family.strip.toLower.replace (" ", ""), this.style.strip.toLower.replace (" ", "")); } @property FT_Encoding charset () { assert (ready ()); if (fface.num_charmaps == 0) return FT_ENCODING_NONE; return fface.charmaps[0].encoding; } @property const(FT_Face) fontFace () const { assert (ready ()); return fface; } @property const(string[]) languages () const { return languages_; } private void findSampleTexts () { assert (ready ()); import std.uni : byGrapheme, isGraphical, byCodePoint, Grapheme; import std.range; void setFallbackSampleTextIfRequired () { if (sampleText_.empty) sampleText_ = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr."; if (sampleIconText_.empty) { import std.conv : text; auto graphemes = sampleText_.byGrapheme; if (graphemes.walkLength > 3) sampleIconText_ = graphemes.array[0..3].byCodePoint.text; else sampleIconText_ = "Aa"; } } dchar getFirstUnichar (string str) { auto g = Grapheme (str); return g[0]; } // determine our sample texts foreach (ref lang; this.languages) { auto plang = pango_language_from_string (lang.toStringz); auto text = pango_language_get_sample_string (plang).fromStringz; if (text is null) continue; sampleText_ = text.dup; auto itP = lang in iconTexts; if (itP !is null) { sampleIconText_ = *itP; break; } } // set some default values if we have been unable to find any texts setFallbackSampleTextIfRequired (); // check if we have a font that can actually display the characters we picked - in case // it doesn't, we just select random chars. if (FT_Get_Char_Index (fface, getFirstUnichar (sampleIconText_)) == 0) { sampleText_ = "☃❤✓☀★☂♞☯☢∞❄♫↺"; sampleIconText_ = "☃❤"; } if (FT_Get_Char_Index (fface, getFirstUnichar (sampleIconText_)) == 0) { import std.uni; sampleText_ = ""; sampleIconText_ = ""; auto count = 0; for (uint map = 0; map < fface.num_charmaps; map++) { auto charmap = fface.charmaps[map]; FT_Set_Charmap (fface, charmap); FT_UInt gindex; auto charcode = FT_Get_First_Char (fface, &gindex); while (gindex != 0) { immutable chc = to!dchar (charcode); if (chc.isGraphical && !chc.isSpace && !chc.isPunctuation) { count++; sampleText_ ~= chc; } if (count >= 24) break; charcode = FT_Get_Next_Char (fface, charcode, &gindex); } if (count >= 24) break; } sampleText_ = sampleText_.strip; // if we were unsuccessful at adding chars, set fallback again // (and in this case, also set the icon text to something useful again) setFallbackSampleTextIfRequired (); } } @property string sampleText () { if (sampleText_.empty) findSampleTexts (); return sampleText_; } @property void sampleText (string val) { if (val.length > 2) sampleText_ = val; } @property string sampleIconText () { if (sampleIconText_.empty) findSampleTexts (); return sampleIconText_; } @property void sampleIconText (string val) { if (val.length <= 3) sampleIconText_ = val; } } unittest { import std.stdio : writeln, File; import std.path : buildPath; import asgen.utils : getTestSamplesDir; writeln ("TEST: ", "Font"); immutable fontFile = buildPath (getTestSamplesDir (), "NotoSans-Regular.ttf"); // test reading from file auto font = new Font (fontFile); assert (font.family == "Noto Sans"); assert (font.style == "Regular"); ubyte[] data; auto f = File (fontFile, "r"); while (!f.eof) { char[512] buf; data ~= f.rawRead (buf); } // test reading from memory font = new Font (data, "test.ttf"); assert (font.family == "Noto Sans"); assert (font.style == "Regular"); assert (font.charset == FT_ENCODING_UNICODE); writeln (font.languages); assert (font.languages == ["en", "aa", "ab", "af", "ak", "an", "ast", "av", "ay", "az-az", "ba", "be", "ber-dz", "bg", "bi", "bin", "bm", "br", "bs", "bua", "ca", "ce", "ch", "chm", "co", "crh", "cs", "csb", "cu", "cv", "cy", "da", "de", "ee", "el", "eo", "es", "et", "eu", "fat", "ff", "fi", "fil", "fj", "fo", "fr", "fur", "fy", "ga", "gd", "gl", "gn", "gv", "ha", "haw", "ho", "hr", "hsb", "ht", "hu", "hz", "ia", "id", "ie", "ig", "ik", "io", "is", "it", "jv", "kaa", "kab", "ki", "kj", "kk", "kl", "kr", "ku-am", "ku-tr", "kum", "kv", "kw", "kwm", "ky", "la", "lb", "lez", "lg", "li", "ln", "lt", "lv", "mg", "mh", "mi", "mk", "mn-mn", "mo", "ms", "mt", "na", "nb", "nds", "ng", "nl", "nn", "no", "nr", "nso", "nv", "ny", "oc", "om", "os", "pap-an", "pap-aw", "pl", "pt", "qu", "quz", "rm", "rn", "ro", "ru", "rw", "sah", "sc", "sco", "se", "sel", "sg", "sh", "shs", "sk", "sl", "sm", "sma", "smj", "smn", "sms", "sn", "so", "sq", "sr", "ss", "st", "su", "sv", "sw", "tg", "tk", "tl", "tn", "to", "tr", "ts", "tt", "tw", "ty", "tyv", "uk", "uz", "ve", "vi", "vo", "vot", "wa", "wen", "wo", "xh", "yap", "yo", "za", "zu"]); } appstream-generator-0.6.8/src/asgen/handlers/000077500000000000000000000000001320016272000211625ustar00rootroot00000000000000appstream-generator-0.6.8/src/asgen/handlers/desktopparser.d000066400000000000000000000273321320016272000242240ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.handlers.desktopparser; import std.path : baseName; import std.uni : toLower; import std.string : format, indexOf, chomp, lastIndexOf, toStringz; import std.array : split, empty; import std.algorithm : startsWith, endsWith, strip, stripRight; import std.stdio; import std.typecons : scoped; import glib.KeyFile; import appstream.Component; import appstream.Provided; import appstream.Icon; import appstream.Launchable : Launchable, LaunchableKind; static import std.regex; import asgen.result; import asgen.utils; import asgen.config : Config, FormatVersion; private string getLocaleFromKey (string key) { if (!localeValid (key)) return null; auto si = key.indexOf ("["); // check if this key is language-specific, if not assume untranslated. if (si <= 0) return "C"; auto locale = key[si+1..$-1]; // drop UTF-8 suffixes locale = chomp (locale, ".utf-8"); locale = chomp (locale, ".UTF-8"); auto delim = locale.lastIndexOf ('.'); if (delim > 0) { // looks like we need to drop another encoding suffix // (but we need to make sure it actually is one) auto enc = locale[delim+1..$]; if ((enc !is null) && (enc.toLower ().startsWith ("iso"))) { locale = locale[0..delim]; } } return locale; } private string getValue (KeyFile kf, string key) { string val; try { val = kf.getString (DESKTOP_GROUP, key); } catch (Throwable) { val = null; } // some dumb .desktop files contain non-printable characters. If we are in XML mode, // this will hard-break the XML reader at a later point, so we need to clean this up // and replace these characters with a nice questionmark, so someone will clean them up. // TODO: Maybe even emit an issue hint if a non-printable chacater is found? auto re = std.regex.ctRegex!(r"[\x00\x08\x0B\x0C\x0E-\x1F]", "g"); val = std.regex.replaceAll (val, re, "#?#"); return val; } /** * Filter out some useless categories which we don't want to have in the * AppStream metadata. */ private string[] filterCategories (Component cpt, GeneratorResult gres, const(string[]) cats) { import asgen.bindings.appstream_utils; string[] rescats; foreach (string cat; cats) { switch (cat) { case "GTK": case "Qt": case "GNOME": case "KDE": case "GUI": case "Application": break; default: if (!cat.empty && !cat.toLower.startsWith ("x-")) { if (as_utils_is_category_name (cat.toStringz)) rescats ~= cat; else gres.addHint (cpt, "category-name-invalid", ["category": cat]); } } } return rescats; } Component parseDesktopFile (GeneratorResult gres, string fname, string data, bool ignore_nodisplay = false) { auto fnameBase = baseName (fname); auto df = scoped!KeyFile (); try { df.loadFromData (data, -1, GKeyFileFlags.KEEP_TRANSLATIONS); } catch (Exception e) { // there was an error gres.addHint (fnameBase, "desktop-file-error", e.msg); return null; } try { // check if we should ignore this .desktop file auto dtype = df.getString (DESKTOP_GROUP, "Type"); if (dtype.toLower () != "application") { // ignore this file, it isn't describing an application return null; } } catch (Throwable) {} try { auto nodisplay = df.getString (DESKTOP_GROUP, "NoDisplay"); if ((!ignore_nodisplay) && (nodisplay.toLower () == "true")) { // we ignore this .desktop file, it's application should not be included return null; } } catch (Throwable) {} try { auto asignore = df.getString (DESKTOP_GROUP, "X-AppStream-Ignore"); if (asignore.toLower () == "true") { // this .desktop file should be excluded from AppStream metadata return null; } } catch (Throwable) { // we don't care if non-essential tags are missing. // if they are not there, the file should be processed. } try { auto hidden = df.getString (DESKTOP_GROUP, "NoDisplay"); if (hidden.toLower () == "true") { gres.addHint (fnameBase, "desktop-file-hidden-set"); if (!ignore_nodisplay) return null; // we ignore this .desktop file } } catch (Throwable) {} /* check this is a valid desktop file */ if (!df.hasGroup (DESKTOP_GROUP)) { gres.addHint (fnameBase, "desktop-file-error", format ("Desktop file '%s' is not a valid desktop file.", fname)); return null; } // make sure we have a valid component to work on auto cpt = gres.getComponent (fnameBase); if (cpt is null) { // try with the shortname as well if (fnameBase.endsWith (".desktop")) { auto fnameBaseNoext = fnameBase[0..$-8]; cpt = gres.getComponent (fnameBaseNoext); } } if (cpt is null) { cpt = new Component (); // strip .desktop suffix if the reverse-domain-name scheme is followed immutable parts = fnameBase.split ("."); if (parts.length > 2 && isTopLevelDomain (parts[0])) cpt.setId (fnameBase[0..$-8]); else cpt.setId (fnameBase); cpt.setKind (ComponentKind.DESKTOP_APP); gres.addComponent (cpt); } void checkDesktopString (string fieldId, string str) { if (((str.startsWith ("\"")) && (str.endsWith ("\""))) || ((str.startsWith ("\'")) && (str.endsWith ("\'")))) { gres.addHint (cpt, "metainfo-quoted-value", ["value": str, "field": fieldId]); } } immutable hadExistingCptName = !cpt.getName ().empty; immutable hadExistingCptSummary = !cpt.getSummary ().empty; size_t dummy; auto keys = df.getKeys (DESKTOP_GROUP, dummy); foreach (string key; keys) { string locale; locale = getLocaleFromKey (key); if (locale is null) continue; if (key.startsWith ("Name")) { if (hadExistingCptName) continue; immutable val = getValue (df, key); checkDesktopString (key, val); /* run backend specific hooks */ auto translations = gres.pkg.getDesktopFileTranslations (df, val); translations[locale] = val; foreach (key, value; translations) cpt.setName (value, key); } else if (key.startsWith ("Comment")) { if (hadExistingCptSummary) continue; immutable val = getValue (df, key); checkDesktopString (key, val); auto translations = gres.pkg.getDesktopFileTranslations (df, val); translations[locale] = val; foreach (ref key, ref value; translations) cpt.setSummary (value, key); } else if (key == "Categories") { auto value = getValue (df, key); auto cats = value.split (";"); cats = filterCategories (cpt, gres, cats); if (cats.empty) continue; foreach (ref c; cats) cpt.addCategory (c); } else if (key.startsWith ("Keywords")) { auto val = getValue (df, key); auto translations = gres.pkg.getDesktopFileTranslations (df, val); translations[locale] = val; foreach (ref key, ref value; translations) { auto kws = value.split (";").stripRight (""); if (kws.empty) continue; cpt.setKeywords (kws, key); } } else if (key == "MimeType") { auto value = getValue (df, key); immutable mts = value.split (";"); if (mts.empty) continue; Provided prov = cpt.getProvidedForKind (ProvidedKind.MIMETYPE); if (prov is null) { prov = new Provided (); prov.setKind (ProvidedKind.MIMETYPE); } foreach (ref mt; mts) { if (!mt.empty) prov.addItem (mt); } cpt.addProvided (prov); } else if (key == "Icon") { auto icon = new Icon (); icon.setKind (IconKind.STOCK); icon.setName (getValue (df, key)); cpt.addIcon (icon); } } // add this .desktop file as launchable entry, if we don't have one set already if (cpt.getLaunchable (LaunchableKind.DESKTOP_ID) is null) { auto launch = new Launchable; launch.setKind (LaunchableKind.DESKTOP_ID); launch.addEntry (fnameBase); cpt.addLaunchable (launch); } return cpt; } unittest { import std.stdio: writeln; import asgen.backends.dummy.dummypkg; writeln ("TEST: ", ".desktop file parser"); auto data = "[Desktop Entry]\n" ~ "Name=FooBar\n" ~ "Name[de_DE]=FööBär\n" ~ "Comment=A foo-ish bar.\n" ~ "Keywords=Flubber;Test;Meh;\n" ~ "Keywords[de_DE]=Goethe;Schiller;Kant;\n"; auto pkg = new DummyPackage ("pkg", "1.0", "amd64"); auto res = new GeneratorResult (pkg); auto cpt = parseDesktopFile (res, "foobar.desktop", data, false); assert (cpt !is null); cpt = res.getComponent ("foobar.desktop"); assert (cpt !is null); assert (cpt.getName () == "FooBar"); assert (cpt.getKeywords () == ["Flubber", "Test", "Meh"]); cpt.setActiveLocale ("de_DE"); assert (cpt.getName () == "FööBär"); assert (cpt.getKeywords () == ["Goethe", "Schiller", "Kant"]); // test component-id trimming res = new GeneratorResult (pkg); cpt = parseDesktopFile (res, "org.example.foobar.desktop", data, false); assert (cpt !is null); cpt = res.getComponent ("org.example.foobar"); assert (cpt !is null); // test preexisting component res = new GeneratorResult (pkg); auto ecpt = new Component (); ecpt.setKind (ComponentKind.DESKTOP_APP); ecpt.setId ("org.example.foobar"); ecpt.setName ("TestX", "C"); ecpt.setSummary ("Summary of TestX", "C"); res.addComponent (ecpt); cpt = parseDesktopFile (res, "org.example.foobar.desktop", data, false); assert (cpt !is null); cpt = res.getComponent ("org.example.foobar"); assert (cpt !is null); assert (cpt.getName () == "TestX"); assert (cpt.getSummary () == "Summary of TestX"); assert (cpt.getKeywords () == ["Flubber", "Test", "Meh"]); // test launchable import std.string : fromStringz; auto launch = cpt.getLaunchable (LaunchableKind.DESKTOP_ID); assert (launch); auto launchEntries = launch.getEntries; assert (launchEntries.len == 1); assert ((cast(char*) launchEntries.index (0)).fromStringz == "org.example.foobar.desktop"); } appstream-generator-0.6.8/src/asgen/handlers/fonthandler.d000066400000000000000000000217001320016272000236330ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.handlers.fonthandler; import std.path : baseName, buildPath; import std.array : appender, replace, empty; import std.string : format, fromStringz, startsWith, endsWith, strip, toLower; import std.conv : to; import appstream.Component; import appstream.Icon; import appstream.Screenshot; static import appstream.Image; static import std.file; import asgen.utils; import asgen.logging; import asgen.result; import asgen.image : Canvas; import asgen.font : Font; import asgen.handlers.iconhandler : wantedIconSizes; private immutable fontScreenshotSizes = [ImageSize (1024, 78), ImageSize (640, 48)]; void processFontData (GeneratorResult gres, string mediaExportDir) { // create a map of all fonts we have in this package Font[string] allFonts; foreach (ref fname; gres.pkg.contents) { if (!fname.startsWith ("/usr/share/fonts/")) continue; if (!fname.endsWith (".ttf", ".otf")) continue; // TODO: Can we support more font types? const(ubyte)[] fdata; try { fdata = gres.pkg.getFileData (fname); } catch (Exception e) { gres.addHint (null, "pkg-extract-error", ["fname": fname.baseName, "pkg_fname": gres.pkg.filename.baseName, "error": e.msg]); return; } immutable fontBaseName = fname.baseName; logDebug ("Reading font %s", fontBaseName); // the font class locks the global mutex internally when reading data with Fontconfig Font font; try { font = new Font (fdata, fontBaseName); } catch (Exception e) { gres.addHint (null, "font-load-error", ["fname": fontBaseName, "pkg_fname": gres.pkg.filename.baseName, "error": e.msg]); return; } allFonts[font.fullName.toLower] = font; } foreach (ref cpt; gres.getComponents ()) { if (cpt.getKind () != ComponentKind.FONT) continue; processFontDataForComponent (gres, cpt, allFonts, mediaExportDir); } } void processFontDataForComponent (GeneratorResult gres, Component cpt, ref Font[string] allFonts, string mediaExportDir) { immutable gcid = gres.gcidForComponent (cpt); if (gcid is null) { gres.addHint (cpt, "internal-error", "No global ID could be found for the component."); return; } auto fontHints = appender!(string[]); auto provided = cpt.getProvidedForKind (ProvidedKind.FONT); if (provided !is null) { auto fontHintsArr = provided.getItems (); for (uint i = 0; i < fontHintsArr.len; i++) { auto fontFullName = (cast(char*) fontHintsArr.index (i)).fromStringz; fontHints ~= to!string (fontFullName).toLower; } } // data export paths immutable cptIconsPath = buildPath (mediaExportDir, gcid, "icons"); immutable cptScreenshotsPath = buildPath (mediaExportDir, gcid, "screenshots"); // if we have no fonts hints, we simply process all the fonts // we found n this package. auto selectedFonts = appender!(Font[]); if (fontHints.data.length == 0) { foreach (ref font; allFonts.byValue) selectedFonts ~= font; } else { // find fonts based on the hints we have // the hint as well as the dictionary keys are all lowercased, so we // can do case-insensitive matching here. foreach (ref fontHint; fontHints.data) { auto fontP = fontHint in allFonts; if (fontP is null) continue; selectedFonts ~= *fontP; } } // we have nothing to do if we did not select any font // (this is a bug, since we filtered for font metainfo previously) if (selectedFonts.data.length == 0) { gres.addHint (cpt, "font-metainfo-but-no-font"); return; } logDebug ("Rendering font data for %s", gcid); // process font files auto hasIcon = false; foreach (ref font; selectedFonts.data) { logDebug ("Processing font '%s'", font.id); // add language information foreach (ref lang; font.languages) { cpt.addLanguage (lang, 80); } // render an icon for our font if (!hasIcon) hasIcon = renderFontIcon (gres, font, cptIconsPath, cpt); } // render all sample screenshots for all font styles we have renderFontScreenshots (gres, selectedFonts.data, cptScreenshotsPath, cpt); } /** * Render an icon for this font package using one of its fonts. * (Since we have no better way to do this, we just pick the first font * at time) **/ private bool renderFontIcon (GeneratorResult gres, Font font, immutable string cptIconsPath, Component cpt) { foreach (ref size; wantedIconSizes) { immutable path = buildPath (cptIconsPath, size.toString); std.file.mkdirRecurse (path); // check if we have a custom icon text value (useful for symbolic fonts) immutable customIconText = cpt.getCustomValue ("FontIconText"); if (!customIconText.empty) font.sampleIconText = customIconText; // Font will ensure that the value does not exceed 3 chars immutable fid = font.id; immutable iconName = format ("%s_%s.png", gres.pkgname, fid); immutable iconStoreLocation = buildPath (path, iconName); if (!std.file.exists (iconStoreLocation)) { // we didn't create an icon yet - render it auto cv = new Canvas (size.width, size.height); cv.drawTextLine (font, font.sampleIconText); cv.savePng (iconStoreLocation); } auto icon = new Icon (); icon.setKind (IconKind.CACHED); icon.setWidth (size.width); icon.setHeight (size.height); icon.setName (iconName); cpt.addIcon (icon); } return true; } /** * Render a "screenshot" sample for this font. **/ private bool renderFontScreenshots (GeneratorResult gres, Font[] fonts, immutable string cptScreenshotsPath, Component cpt) { std.file.mkdirRecurse (cptScreenshotsPath); auto first = true; foreach (ref font; fonts) { immutable fid = font.id; if (fid is null) { logWarning ("%s: Ignored font screenshot rendering due to missing ID:", cpt.getId ()); continue; } auto scr = new Screenshot (); if (first) scr.setKind (ScreenshotKind.DEFAULT); else scr.setKind (ScreenshotKind.EXTRA); scr.setCaption ("%s %s".format (font.family, font.style), "C"); if (first) first = false; // check if we have a custom sample text value (useful for symbolic fonts) // we set this value for every fonr in the font-bundle, there is no way for this // hack to select which font face should have the sample text. // Since this hack only affects very few exotic fonts and should generally not // be used, this should not be an issue. immutable customSampleText = cpt.getCustomValue ("FontSampleText"); if (!customSampleText.empty) font.sampleIconText = customSampleText; auto cptScreenshotsUrl = buildPath (gres.gcidForComponent (cpt), "screenshots"); foreach (ref size; fontScreenshotSizes) { immutable imgName = "image-%s_%s.png".format (fid, size.toString); immutable imgFileName = buildPath (cptScreenshotsPath, imgName); immutable imgUrl = buildPath (cptScreenshotsUrl, imgName); if (!std.file.exists (imgFileName)) { // we didn't create s screenshot yet - render it auto cv = new Canvas (size.width, size.height); cv.drawTextLine (font, font.sampleText); cv.savePng (imgFileName); } auto img = new appstream.Image.Image (); img.setKind (ImageKind.THUMBNAIL); img.setWidth (size.width); img.setHeight (size.height); img.setUrl (imgUrl); scr.addImage (img); } cpt.addScreenshot (scr); } return true; } appstream-generator-0.6.8/src/asgen/handlers/iconhandler.d000066400000000000000000000654011320016272000236230ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.handlers.iconhandler; import std.stdio; import std.string; import std.array : replace; import std.path : baseName, buildPath; import std.uni : toLower; import std.file : mkdirRecurse; import std.algorithm : canFind; import std.variant; import std.parallelism; import std.typecons : scoped; import std.concurrency : Generator, yield; import glib.KeyFile; import appstream.Component; import appstream.Icon; static import std.file; import asgen.utils; import asgen.logging; import asgen.result; import asgen.image; import asgen.backends.interfaces; import asgen.contentsstore; static import asgen.config; // all image extensions that we recognize as possible for icons. // the most favorable file extension needs to come first to prefer it private immutable possibleIconExts = [".png", ".jpg", ".svgz", ".svg", ".gif", ".ico", ".xpm"]; // the image extensions that we will actually allow software to have. private immutable allowedIconExts = [".png", ".jpg", ".svgz", ".svg", ".xpm"]; /// The icon sizes that we are returning to clients public immutable wantedIconSizes = [ImageSize (64), ImageSize (128), ImageSize (64, 64, 2), ImageSize (128, 128, 2)]; /** * Describes an icon theme as specified in the XDG theme spec. */ private final class Theme { private: string name; Algebraic!(int, string)[string][] directories; public: this (string name, const(ubyte)[] indexData) { this.name = name; auto index = new KeyFile (); auto indexText = cast(string) indexData; index.loadFromData (indexText, -1, GKeyFileFlags.NONE); size_t dummy; foreach (section; index.getGroups (dummy)) { string type; string context; int scale; int threshold; int size; int minSize; int maxSize; // we ignore symbolic icons if (section.startsWith("symbolic/")) continue; try { size = index.getInteger (section, "Size"); context = index.getString (section, "Context"); } catch (Throwable) { continue; } try { threshold = index.getInteger (section, "Threshold"); } catch (Throwable) { threshold = 2; } try { type = index.getString (section, "Type"); } catch (Throwable) { type = "Threshold"; } try { minSize = index.getInteger (section, "MinSize"); } catch (Throwable) { minSize = size; } try { maxSize = index.getInteger (section, "MaxSize"); } catch (Throwable) { maxSize = size; } try { scale = index.getInteger (section, "Scale"); } catch (Throwable) { scale = 1; } if (size == 0) continue; auto themedir = [ "path": Algebraic!(int, string) (section), "type": Algebraic!(int, string) (type), "size": Algebraic!(int, string) (size), "minsize": Algebraic!(int, string) (minSize), "maxsize": Algebraic!(int, string) (maxSize), "threshold": Algebraic!(int, string) (threshold), "scale": Algebraic!(int, string) (scale) ]; directories ~= themedir; } // sort our directory list, so the smallest size is at the top import std.algorithm : sort; directories.sort!("a[\"size\"].get!int < b[\"size\"].get!int"); } this (string name, Package pkg) { auto indexData = pkg.getFileData (buildPath ("/usr/share/icons", name, "index.theme")); this (name, indexData); } /** * Check if a directory is suitable for the selected size. * If @assumeThresholdScalable is set to true, we will allow * downscaling of any higher-than-requested icon size, even if the * section is of "Threshold" type and would usually prohibit the scaling. */ private bool directoryMatchesSize (Algebraic!(int, string)[string] themedir, ImageSize size, bool assumeThresholdScalable = false) { int scale = themedir["scale"].get!int; if (scale != size.scale) return false; string type = themedir["type"].get!string; if (type == "Fixed") return size.toInt () == themedir["size"].get!int; if (type == "Scalable") { if ((themedir["minsize"].get!int <= size.toInt) && (size.toInt <= themedir["maxsize"].get!int)) return true; return false; } if (type == "Threshold") { auto themeSize = themedir["size"].get!int; auto th = themedir["threshold"].get!int; if (assumeThresholdScalable) { // we treat this "Threshold" as if we were allowed to downscale its icons if they // have a higher size. // This can lead to "wrong" scaling, but allows us to retrieve more icons. return themeSize >= size.toInt; } else { // follow the proper algorithm as defined by the XDG spec if (((themeSize - th) <= size.toInt) && (size.toInt <= (themeSize + th))) return true; } return false; } return false; } /** * Returns an iteratable of possible icon filenames that match @iname and @size. * If @relaxedScalingRules is set to true, we scale down any bigger icon seize, even * if the theme definition would usually prohibit that. **/ auto matchingIconFilenames (string iname, ImageSize size, bool relaxedScalingRules = false) { auto gen = new Generator!string ( { foreach (themedir; this.directories) { if (directoryMatchesSize (themedir, size, relaxedScalingRules)) { // best filetype needs to come first to be preferred, only types allowed by the spec are handled at all foreach (extension; ["png", "svgz", "svg", "xpm"]) yield ("/usr/share/icons/%s/%s/%s.%s".format (this.name, themedir["path"].get!(string), iname, extension)); } } }); return gen; } } /** * Finds icons in a software archive and stores them in the * correct sizes for a given AppStream component. */ final class IconHandler { private: string mediaExportPath; Theme[] themes; Package[string] iconFiles; string[] themeNames; public: this (string mediaPath, Package[string] pkgMap, string iconTheme = null) { logDebug ("Creating new IconHandler"); mediaExportPath = mediaPath; // Preseeded theme names. // * prioritize hicolor, because that's where apps often install their upstream icon // * then look at the theme given in the config file // * allow Breeze icon theme, needed to support KDE apps (they have no icon at all, otherwise...) // * in rare events, GNOME needs the same treatment, so special-case Adwaita as well // * We need at least one icon theme to provide the default XDG icon spec stock icons. // A fair take would be to select them between KDE and GNOME at random, but for consistency and // because everyone hates unpredictable behavior, we sort alphabetically and prefer Adwaita over Breeze. themeNames = ["hicolor"]; if (iconTheme !is null) themeNames ~= iconTheme; themeNames ~= "Adwaita"; // GNOME themeNames ~= "breeze"; // KDE Package getPackage (string pkid) { if (pkid is null) return null; auto pkgP = (pkid in pkgMap); if (pkgP is null) return null; else return *pkgP; } // open package contents cache auto ccache = scoped!ContentsStore (); ccache.open (asgen.config.Config.get ()); // load data from the contents index. // we don't show mercy to memory here, we just want the icon lookup to be fast, // so we have to cache the data. Theme[string] tmpThemes; auto filesPkids = ccache.getIconFilesMap (pkgMap.keys); foreach (fname; parallel (filesPkids.byKey, 100)) { if (fname.startsWith ("/usr/share/pixmaps/")) { auto pkg = getPackage (filesPkids[fname]); if (pkg is null) continue; synchronized (this) iconFiles[fname] = pkg; continue; } // optimization: check if we actually have an interesting path before // entering the foreach loop. if (!fname.startsWith ("/usr/share/icons/")) continue; auto pkg = getPackage (filesPkids[fname]); if (pkg is null) continue; foreach (name; themeNames) { if (fname == "/usr/share/icons/%s/index.theme".format (name)) { synchronized (this) tmpThemes[name] = new Theme (name, pkg); } else if (fname.startsWith ("/usr/share/icons/%s".format (name))) { synchronized (this) iconFiles[fname] = pkg; } } } // when running on partial repos (e.g. PPAs) we might not have a package containing the // hicolor theme definition. Since we always need it to be there to properly process icons, // we inject our own copy here. if ("hicolor" !in tmpThemes) { logInfo ("No packaged hicolor icon theme found, using built-in one."); auto hicolorThemeIndex = getDataPath ("hicolor-theme-index.theme"); if (!std.file.exists (hicolorThemeIndex)) { logError ("Hicolor icon theme index at '%s' was not found! We will not be able to handle icons in this theme.", hicolorThemeIndex); } else { ubyte[] indexData; auto f = File (hicolorThemeIndex, "r"); while (!f.eof) { char[GENERIC_BUFFER_SIZE] buf; indexData ~= f.rawRead (buf); } tmpThemes["hicolor"] = new Theme ("hicolor", indexData); } } // this is necessary to keep the ordering (and therefore priority) of themes. // we don't know the order in which we find index.theme files in the code above, // therefore this sorting is necessary. foreach (tname; themeNames) { if (tname in tmpThemes) themes ~= tmpThemes[tname]; } logDebug ("Created new IconHandler."); } private string getIconNameAndClear (Component cpt) { string name = null; // a not-processed icon name is stored as "1x1px" icon, so we can // quickly identify it here. auto icon = componentGetStockIcon (cpt); if (!icon.isNull) name = icon.get.getName (); // clear the list of icons in this component auto iconsArray = cpt.getIcons (); if (iconsArray.len > 0) iconsArray.removeRange (0, iconsArray.len); return name; } static private bool iconAllowed (string iconName) { foreach (ref ext; allowedIconExts) if (iconName.endsWith (ext)) return true; return false; } private ImageFormat imageKindFromFile (string fname) { if (fname.endsWith (".png")) return ImageFormat.PNG; if ((fname.endsWith (".jpg")) || (fname.endsWith (".jpeg"))) return ImageFormat.JPEG; if (fname.endsWith (".svg")) return ImageFormat.SVG; if (fname.endsWith (".svgz")) return ImageFormat.SVGZ; if (fname.endsWith (".xpm")) return ImageFormat.XPM; return ImageFormat.UNKNOWN; } /** * Generates potential filenames of the icon that is searched for in the * given size. **/ private auto possibleIconFilenames (string iconName, ImageSize size, bool relaxedScalingRules = false) { auto gen = new Generator!string ( { foreach (theme; this.themes) { foreach (fname; theme.matchingIconFilenames (iconName, size, relaxedScalingRules)) yield (fname); } // check pixmaps for icons foreach (extension; possibleIconExts) yield ("/usr/share/pixmaps/%s%s".format (iconName, extension)); }); return gen; } /** * Helper structure for the findIcons * method. **/ private struct IconFindResult { Package pkg; string fname; this (Package pkg, string fname) { this.pkg = pkg; this.fname = fname; } } /** * Looks up 'icon' with 'size' in popular icon themes according to the XDG * icon theme spec. **/ auto findIcons (string iconName, const ImageSize[] sizes, Package pkg = null) { IconFindResult[ImageSize] sizeMap = null; foreach (size; sizes) { // search for possible icon filenames, using relaxed scaling rules by default foreach (fname; possibleIconFilenames (iconName, size, true)) { if (pkg !is null) { // we are supposed to search in one particular package if (pkg.contents.canFind (fname)) { sizeMap[size] = IconFindResult (pkg, fname); break; } } else { // global search in all packages auto pkgP = (fname in iconFiles); // continue if filename is not in map if (pkgP is null) continue; sizeMap[size] = IconFindResult (*pkgP, fname); break; } } } return sizeMap; } /** * Strip file extension from icon. */ string stripIconExt (ref string iconName) { if (iconName.endsWith (".png")) return iconName[0..$-4]; if (iconName.endsWith (".svg")) return iconName[0..$-4]; if (iconName.endsWith (".xpm")) return iconName[0..$-4]; if (iconName.endsWith (".svgz")) return iconName[0..$-5]; return iconName; } /** * Extracts the icon from the package and stores it in the cache. * Ensures the stored icon always has the size given in "size", and renders * scalable vectorgraphics if necessary. * * Params: * cpt = The component this icon belongs to. * res = The result the component belongs to. * cptExportPath = The data export directory of the component. * sourcePkg = The package the to-be-extracted icon is located in. * iconPath = The (absolute) path to the icon. * size = The size the icon should be stored in. **/ private bool storeIcon (Component cpt, GeneratorResult gres, string cptExportPath, Package sourcePkg, string iconPath, ImageSize size) { auto iformat = imageKindFromFile (iconPath); if (iformat == ImageFormat.UNKNOWN) { gres.addHint (cpt.getId (), "icon-format-unsupported", ["icon_fname": baseName (iconPath)]); return false; } auto path = buildPath (cptExportPath, "icons", size.toString ()); auto iconName = "%s_%s".format (gres.pkgname, baseName (iconPath)); if (iconName.endsWith (".svgz")) iconName = iconName.replace (".svgz", ".png"); else if (iconName.endsWith (".svg")) iconName = iconName.replace (".svg", ".png"); else if (iconName.endsWith (".xpm")) iconName = iconName.replace (".xpm", ".png"); auto iconStoreLocation = buildPath (path, iconName); if (std.file.exists (iconStoreLocation)) { // we already extracted that icon, skip the extraction step // and just add the new icon. auto icon = new Icon (); icon.setKind (IconKind.CACHED); icon.setWidth (size.width); icon.setHeight (size.height); icon.setScale (size.scale); icon.setName (iconName); cpt.addIcon (icon); return true; } // filepath is checked because icon can reside in another binary // eg amarok's icon is in amarok-data ubyte[] iconData = null; try { iconData = cast(ubyte[]) sourcePkg.getFileData (iconPath); } catch (Exception e) { gres.addHint(cpt.getId (), "pkg-extract-error", ["fname": baseName (iconPath), "pkg_fname": baseName (sourcePkg.filename), "error": e.msg]); return false; } if (iconData.empty ()) { gres.addHint (cpt.getId (), "pkg-empty-file", ["fname": baseName (iconPath), "pkg_fname": baseName (sourcePkg.filename)]); return false; } auto scaled_width = size.width * size.scale; auto scaled_height = size.height * size.scale; if ((iformat == ImageFormat.SVG) || (iformat == ImageFormat.SVGZ)) { // create target directory mkdirRecurse (path); try { auto cv = new Canvas (scaled_width, scaled_height); cv.renderSvg (iconData); cv.savePng (iconStoreLocation); delete cv; } catch (Exception e) { gres.addHint(cpt.getId (), "image-write-error", ["fname": baseName (iconPath), "pkg_fname": baseName (sourcePkg.filename), "error": e.msg]); return false; } } else { Image img; try { img = new Image (iconData, iformat); } catch (Exception e) { gres.addHint(cpt.getId (), "image-write-error", ["fname": baseName (iconPath), "pkg_fname": baseName (sourcePkg.filename), "error": e.msg]); return false; } if (iformat == ImageFormat.XPM) { // we use XPM images only if they are large enough if ((img.width < scaled_width) || (img.height < scaled_height)) return false; } // create target directory mkdirRecurse (path); try { img.scale (scaled_width, scaled_height); img.savePng (iconStoreLocation); } catch (Exception e) { gres.addHint(cpt.getId (), "image-write-error", ["fname": baseName (iconPath), "pkg_fname": baseName (sourcePkg.filename), "error": e.msg]); return false; } delete img; } auto icon = new Icon (); icon.setKind (IconKind.CACHED); icon.setWidth (size.width); icon.setHeight (size.height); icon.setScale (size.scale); icon.setName (iconName); cpt.addIcon (icon); return true; } bool process (GeneratorResult gres, Component cpt) { auto iconName = getIconNameAndClear (cpt); // nothing to do if there is no icon if (iconName is null) return true; auto gcid = gres.gcidForComponent (cpt); if (gcid is null) { auto cid = cpt.getId (); if (cid is null) cid = "general"; gres.addHint (cid, "internal-error", "No global ID could be found for the component."); return false; } logDebug ("Looking for icon '%s' for '%s::%s'", iconName, gres.pkid, cpt.getId); auto cptMediaPath = buildPath (mediaExportPath, gcid); if (iconName.startsWith ("/")) { if (gres.pkg.contents.canFind (iconName)) return storeIcon (cpt, gres, cptMediaPath, gres.pkg, iconName, ImageSize (64, 64)); } else { iconName = baseName (iconName); // Small hack: Strip .png and other extensions from icon files to make the XDG and Pixmap finder // work properly, which add their own icon extensions and find the most suitable icon. iconName = stripIconExt (iconName); string lastIconName = null; /// Search for an icon in XDG icon directories. /// Returns true on success and sets lastIconName to the /// last icon name that has been handled. bool findAndStoreXdgIcon (Package epkg = null) { auto iconRes = findIcons (iconName, wantedIconSizes, epkg); if (iconRes is null) return false; IconFindResult[ImageSize] iconsStored; foreach (size; wantedIconSizes) { auto infoP = (size in iconRes); IconFindResult info; info.pkg = null; if (infoP !is null) info = *infoP; if (info.pkg is null) { // the size we want wasn't found, can we downscale a larger one? foreach (asize; iconRes.byKey ()) { auto data = iconRes[asize]; if (asize < size) continue; info = data; break; } } // give up if we still haven't found an icon if (info.pkg is null) continue; lastIconName = info.fname; if (iconAllowed (lastIconName)) { if (storeIcon (cpt, gres, cptMediaPath, info.pkg, lastIconName, size)) iconsStored[size] = info; } else { // the found icon is not suitable, but maybe a larger one is available that we can downscale? foreach (asize; iconRes.byKey ()) { auto data = iconRes[asize]; if (asize < size) continue; info = data; break; } if (iconAllowed (info.fname)) { if (storeIcon (cpt, gres, cptMediaPath, info.pkg, lastIconName, size)) iconsStored[size] = info; lastIconName = info.fname; } } } // ensure we have stored a 64x64px icon, since this is mandated // by the AppStream spec by downscaling a larger icon that we // might have found. if (ImageSize(64) !in iconsStored) { foreach (size; wantedIconSizes) { if (size !in iconsStored) continue; if (size < ImageSize(64)) continue; auto info = iconsStored[size]; lastIconName = info.fname; if (storeIcon (cpt, gres, cptMediaPath, info.pkg, lastIconName, ImageSize(64))) return true; } } else { return true; } return false; } // search for the right icon iside the current package auto success = findAndStoreXdgIcon (gres.pkg); if ((!success) && (!gres.isIgnored (cpt))) { // search in all packages success = findAndStoreXdgIcon (); if (success) { // we found a valid stock icon, so set that additionally to the cached one auto icon = new Icon (); icon.setKind (IconKind.STOCK); icon.setName (iconName); cpt.addIcon (icon); } else if ((lastIconName !is null) && (!iconAllowed (lastIconName))) { gres.addHint (cpt.getId (), "icon-format-unsupported", ["icon_fname": baseName (lastIconName)]); } } if ((!success) && (lastIconName is null)) { gres.addHint (cpt.getId (), "icon-not-found", ["icon_fname": iconName]); return false; } } return true; } } unittest { writeln ("TEST: ", "IconHandler"); auto hicolorThemeIndex = getDataPath ("hicolor-theme-index.theme"); ubyte[] indexData; auto f = File (hicolorThemeIndex, "r"); while (!f.eof) { char[GENERIC_BUFFER_SIZE] buf; indexData ~= f.rawRead (buf); } auto theme = new Theme ("hicolor", indexData); foreach (fname; theme.matchingIconFilenames ("accessories-calculator", ImageSize (48))) { bool valid = false; if (fname.startsWith ("/usr/share/icons/hicolor/48x48/")) valid = true; if (fname.startsWith ("/usr/share/icons/hicolor/scalable/")) valid = true; assert (valid); if ((valid) && (IconHandler.iconAllowed (fname))) valid = true; else valid = false; if (fname.endsWith (".ico")) assert (!valid); else assert (valid); } foreach (fname; theme.matchingIconFilenames ("accessories-text-editor", ImageSize (192))) { if (fname.startsWith ("/usr/share/icons/hicolor/192x192/")) continue; if (fname.startsWith ("/usr/share/icons/hicolor/256x256/")) continue; if (fname.startsWith ("/usr/share/icons/hicolor/512x512/")) continue; if (fname.startsWith ("/usr/share/icons/hicolor/scalable/")) continue; assert (0); } } appstream-generator-0.6.8/src/asgen/handlers/metainfoparser.d000066400000000000000000000050251320016272000243500ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.handlers.metainfoparser; import std.path : baseName; import std.uni : toLower; import std.string : format; import std.array : empty; import std.stdio; import appstream.Metadata; import appstream.Component; import asgen.result; import asgen.utils; private bool isMetainfoLicense (string license) pure { import asgen.bindings.appstream_utils; import std.string : toStringz; return as_license_is_metadata_license (license.toStringz); } Component parseMetaInfoFile (Metadata mdata, GeneratorResult gres, const string data, const string mfname) { try { mdata.parse (data, FormatKind.XML); } catch (Exception e) { gres.addHint ("general", "metainfo-parsing-error", e.msg); return null; } auto cpt = mdata.getComponent (); if (cpt is null) return null; // check if we have a component-id, a component without ID is invalid if (cpt.getId.empty) { gres.addHint (null, "metainfo-no-id", ["fname": mfname]); return null; } gres.addComponent (cpt); // check if we can actually legally use this metadata if (!isMetainfoLicense (cpt.getMetadataLicense())) { gres.addHint (cpt, "metainfo-license-invalid", ["license": cpt.getMetadataLicense()]); return null; } // quit immediately if we have an unknown component type if (cpt.getKind () == ComponentKind.UNKNOWN) { gres.addHint (cpt, "metainfo-unknown-type"); return null; } return cpt; } Component parseMetaInfoFile (GeneratorResult gres, const string data, const string mfname) { auto mdata = new Metadata (); mdata.setLocale ("ALL"); mdata.setFormatStyle (FormatStyle.METAINFO); return parseMetaInfoFile (mdata, gres, data, mfname); } appstream-generator-0.6.8/src/asgen/handlers/metainfovalidator.d000066400000000000000000000046231320016272000250440ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.handlers.metainfovalidator; import std.path : baseName; import std.uni : toLower; import std.string : format; import std.stdio; import std.typecons : scoped; import appstream.Validator; import appstream.ValidatorIssue; import appstream.Component; import glib.ListG; import gobject.ObjectG; import asgen.result; import asgen.utils; void validateMetaInfoFile (GeneratorResult res, Component cpt, string data) { auto validator = scoped!Validator (); validator.setCheckUrls (false); // don't check web URLs for validity try { validator.validateData (data); } catch (Exception e) { res.addHint (cpt.getId (), "metainfo-validation-issue", "The file could not be validated due to an error: " ~ e.msg); return; } auto issueList = validator.getIssues (); for (ListG l = issueList; l !is null; l = l.next) { auto issue = ObjectG.getDObject!ValidatorIssue (cast (typeof(ValidatorIssue.tupleof[0])) l.data); // we have a special hint tag for legacy metadata if (issue.getKind () == IssueKind.LEGACY) { res.addHint (cpt.getId (), "ancient-metadata"); continue; } auto importance = issue.getImportance (); auto msg = issue.getMessage(); // we ignore pedantic hints by default and don't store or display them if (importance == IssueImportance.PEDANTIC) continue; if (importance == IssueImportance.INFO) res.addHint (cpt.getId (), "metainfo-validation-hint", msg); else res.addHint (cpt.getId (), "metainfo-validation-issue", msg); } } appstream-generator-0.6.8/src/asgen/handlers/package.d000066400000000000000000000021201320016272000227150ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.handlers; public import asgen.handlers.desktopparser; public import asgen.handlers.fonthandler; public import asgen.handlers.iconhandler; public import asgen.handlers.metainfoparser; public import asgen.handlers.metainfovalidator; public import asgen.handlers.screenshothandler; appstream-generator-0.6.8/src/asgen/handlers/screenshothandler.d000066400000000000000000000154401320016272000250460ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.handlers.screenshothandler; import std.path : baseName, buildPath; import std.uni : toLower; import std.string : format; import std.array : empty; import std.algorithm : startsWith; import std.stdio; import gobject.ObjectG; import appstream.c.functions; import appstream.Component; import appstream.Screenshot; import appstream.Image; static import std.file; import asgen.config; import asgen.result; import asgen.utils; static import asgen.image; private immutable screenshotSizes = [ImageSize (1248, 702), ImageSize (752, 423), ImageSize (624, 351), ImageSize (224, 126)]; void processScreenshots (GeneratorResult gres, Component cpt, string mediaExportDir) { auto scrArr = cpt.getScreenshots (); if (scrArr.len == 0) return; Screenshot[] validScrs; for (uint i = 0; i < scrArr.len; i++) { // cast array data to D Screenshot and keep a reference to the C struct auto scr = new Screenshot (cast (AsScreenshot*) scrArr.index (i)); auto resScr = processScreenshot (gres, cpt, scr, mediaExportDir, i+1); if (resScr !is null) { validScrs ~= resScr; resScr.doref (); } } // drop all screenshots from the component scrArr.removeRange (0, scrArr.len); // add valid screenshots back foreach (ref scr; validScrs) { cpt.addScreenshot (scr); } } private Screenshot processScreenshot (GeneratorResult gres, Component cpt, Screenshot scr, string mediaExportDir, uint scrNo) { import std.stdio; auto imgArr = scr.getImages (); if (imgArr.len == 0) { gres.addHint (cpt.getId (), "metainfo-screenshot-but-no-image"); return null; } auto initImg = new Image (cast(AsImage*) imgArr.index (0)); initImg.doref (); // drop all images imgArr.removeRange (0, imgArr.len); auto conf = asgen.config.Config.get (); auto origImgUrl = initImg.getUrl (); ubyte[] imgData; try { import std.net.curl; if (origImgUrl.startsWith ("ftp:")) { // we have an FTP url imgData = get!(AutoProtocol, ubyte) (origImgUrl); } else { // assume HTTP(S) auto http = HTTP (); if (!conf.caInfo.empty ()) http.caInfo = conf.caInfo; imgData = get!(HTTP, ubyte) (origImgUrl, http); } } catch (Exception e) { gres.addHint (cpt.getId (), "screenshot-download-error", ["url": origImgUrl, "error": e.msg]); return null; } auto gcid = gres.gcidForComponent (cpt); if (gcid is null) { gres.addHint (cpt, "internal-error", "No global ID could be found for the component."); return null; } immutable cptScreenshotsPath = buildPath (mediaExportDir, gcid, "screenshots"); immutable cptScreenshotsUrl = buildPath (gcid, "screenshots"); std.file.mkdirRecurse (cptScreenshotsPath); uint sourceScrWidth; uint sourceScrHeight; try { auto srcImgName = format ("image-%s_orig.png", scrNo); auto srcImgPath = buildPath (cptScreenshotsPath, srcImgName); auto srcImgUrl = buildPath (cptScreenshotsUrl, srcImgName); // save the source screenshot as PNG image auto srcImg = new asgen.image.Image (imgData, asgen.image.ImageFormat.PNG); srcImg.savePng (srcImgPath); auto img = new Image (); img.setKind (ImageKind.SOURCE); sourceScrWidth = srcImg.width; sourceScrHeight = srcImg.height; img.setWidth (sourceScrWidth); img.setHeight (sourceScrHeight); // if we should not create a screenshots store, delete the just-downloaded file and set // the original upstream URL as source. // we still needed to download the screenshot to get information about its size. if (!conf.featureEnabled (GeneratorFeature.STORE_SCREENSHOTS)) { img.setUrl (origImgUrl); scr.addImage (img); // drop screenshot storage directory, in this mode it was only for temporary use std.file.rmdirRecurse (cptScreenshotsPath); return scr; } img.setUrl (srcImgUrl); scr.addImage (img); } catch (Exception e) { gres.addHint (cpt.getId (), "screenshot-save-error", ["url": origImgUrl, "error": format ("Can not store source screenshot: %s", e.msg)]); return null; } // generate & save thumbnails for the screenshot image bool thumbnailsGenerated = false; foreach (size; screenshotSizes) { // ensure we will only downscale the screenshot for thumbnailing if (size.width > sourceScrWidth) continue; if (size.height > sourceScrHeight) continue; try { auto thumb = new asgen.image.Image (imgData, asgen.image.ImageFormat.PNG); if (size.width > size.height) thumb.scaleToWidth (size.width); else thumb.scaleToHeight (size.height); // create thumbnail storage path and URL component auto thumbImgName = "image-%s_%sx%s.png".format (scrNo, thumb.width, thumb.height); auto thumbImgPath = buildPath (cptScreenshotsPath, thumbImgName); auto thumbImgUrl = buildPath (cptScreenshotsUrl, thumbImgName); // store the thumbnail image on disk thumb.savePng (thumbImgPath); // finally prepare the thumbnail definition and add it to the metadata auto img = new Image (); img.setKind (ImageKind.THUMBNAIL); img.setWidth (thumb.width); img.setHeight (thumb.height); img.setUrl (thumbImgUrl); scr.addImage (img); } catch (Exception e) { gres.addHint (cpt.getId (), "screenshot-save-error", ["url": origImgUrl, "error": format ("Failure while preparing thumbnail: %s", e.msg)]); return null; } thumbnailsGenerated = true; } if (!thumbnailsGenerated) gres.addHint (cpt.getId (), "screenshot-no-thumbnails", ["url": origImgUrl]); return scr; } appstream-generator-0.6.8/src/asgen/hint.d000066400000000000000000000124261320016272000204760ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.hint; import std.stdio; import std.string; import std.json; import asgen.logging; import asgen.utils; alias HintList = GeneratorHint[]; /** * Severity assigned with an issue hint. * * INFO: Information, no immediate action needed (but will likely be an issue later). * WARNING: An issue which did not prevent generating meaningful data, but which is still serious * and should be fixed (warning of this kind usually result in less data). * ERROR: A fatal error which resulted in the component being excluded from the final metadata. */ enum HintSeverity { UNKNOWN, INFO, WARNING, ERROR } @safe private HintSeverity severityFromString (string str) pure { switch (str) { case "error": return HintSeverity.ERROR; case "warning": return HintSeverity.WARNING; case "info": return HintSeverity.INFO; default: return HintSeverity.UNKNOWN; } } final class GeneratorHint { private: string tag; string cid; string[string] vars; HintSeverity severity; public: @trusted this (string tag, string cid = null) { this.tag = tag; this.cid = cid; severity = HintsStorage.get ().getSeverity (tag); if (severity == HintSeverity.UNKNOWN) logWarning ("Severity of hint tag '%s' is unknown. This likely means that this tag is not registered and should not be emitted.", tag); } @safe bool isError () pure { return severity == HintSeverity.ERROR; } @safe void setVars (string[string] vars) pure { this.vars = vars; } @safe auto toJsonNode () pure { JSONValue json = JSONValue(["tag": JSONValue (tag), "vars": JSONValue (vars) ]); return json; } } /** * Singleton holding information about the hint tags we know about. **/ final class HintsStorage { // Thread local private static bool instantiated_; // Thread global private __gshared HintsStorage instance_; static HintsStorage get() { if (!instantiated_) { synchronized (HintsStorage.classinfo) { if (!instance_) instance_ = new HintsStorage (); instantiated_ = true; } } return instance_; } struct HintDefinition { string tag; string text; HintSeverity severity; bool internal; } private HintDefinition[string] hintDefs; @trusted private this () { import std.path; static import std.file; // find the hint definition file auto hintsDefFile = getDataPath ("asgen-hints.json"); if (!std.file.exists (hintsDefFile)) { logError ("Hints definition file '%s' was not found! This means we can not determine severity of issue tags and not render report pages.", hintsDefFile); return; } // read the hints definition JSON file auto f = File (hintsDefFile, "r"); string jsonData; string line; while ((line = f.readln ()) !is null) jsonData ~= line; auto hintDefsJSON = parseJSON (jsonData); foreach (tag; hintDefsJSON.object.byKey ()) { auto j = hintDefsJSON[tag]; auto def = HintDefinition (); def.tag = tag; def.severity = severityFromString (j["severity"].str); if (j["text"].type == JSON_TYPE.ARRAY) { foreach (l; j["text"].array) def.text ~= l.str ~ "\n"; } else { def.text = j["text"].str; } if ("internal" in j) def.internal = j["internal"].type == JSON_TYPE.TRUE; hintDefs[tag] = def; } } @safe HintDefinition getHintDef (string tag) pure { auto defP = (tag in hintDefs); if (defP is null) return HintDefinition (); return *defP; } @safe HintSeverity getSeverity (string tag) pure { auto hDef = getHintDef (tag); return hDef.severity; } } unittest { writeln ("TEST: ", "Issue Hints"); auto hint = new GeneratorHint ("just-a-unittest", "org.freedesktop.foobar.desktop"); hint.vars = ["rainbows": "yes", "unicorns": "no", "storage": "towel"]; auto root = hint.toJsonNode (); writeln (root.toJSON (true)); HintsStorage.get (); } appstream-generator-0.6.8/src/asgen/image.d000066400000000000000000000330321320016272000206120ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.image; import std.stdio; import std.string; import std.conv : to; import std.path : baseName; import std.math; import core.stdc.stdarg; import core.stdc.stdio; import asgen.bindings.cairo; import asgen.bindings.rsvg; import asgen.bindings.gdkpixbuf; import glib.c.types; import glib.c.functions; import asgen.logging; import asgen.config; import asgen.font : Font; import core.sync.mutex; private __gshared Mutex fontconfigMutex = null; enum ImageFormat { UNKNOWN, PNG, JPEG, GIF, SVG, SVGZ, XPM } private void optimizePNG (string fname) { import std.process; auto conf = asgen.config.Config.get (); if (!conf.featureEnabled (GeneratorFeature.OPTIPNG)) return; // NOTE: Maybe add an option to run optipng with stronger optimization? (>= -o4) auto optipng = execute (["optipng", fname ]); if (optipng.status != 0) logWarning ("Optipng on '%s' failed with error code %s: %s", fname, optipng.status, optipng.output); } /** * Helper method required so we do not modify the Fontconfig * global state while reading it with another process. * * This prevents a weird deadlock when multiple threads are * redering stuff that contains fonts. **/ private void enterFontconfigCriticalSection () @trusted { if (fontconfigMutex is null) return; fontconfigMutex.lock (); } /** * Helper method required so we do not modify the Fontconfig * global state while reading it with another process. * * This prevents a weird deadlock when multiple threads are * redering stuff that contains fonts. **/ private void leaveFontconfigCriticalSection () @trusted { if (fontconfigMutex is null) return; fontconfigMutex.unlock (); } public void setupFontconfigMutex () @trusted { fontconfigMutex = new Mutex; } final class Image { private: GdkPixbuf pix; public: private void throwGError (GError *error, string pretext = null) { if (error !is null) { auto msg = fromStringz (error.message).dup; g_error_free (error); if (pretext is null) throw new Exception (to!string (msg)); else throw new Exception (format ("%s: %s", pretext, to!string (msg))); } } this (string fname) { GError *error = null; pix = gdk_pixbuf_new_from_file (fname.toStringz (), &error); throwGError (error, format ("Unable to open image '%s'", baseName (fname))); } this (ubyte[] imgBytes, ImageFormat ikind) { import gio.c.functions; import gio.MemoryInputStream; auto istream = new MemoryInputStream (); istream.addData (imgBytes, null); GError *error = null; pix = gdk_pixbuf_new_from_stream (cast(GInputStream*) istream.getMemoryInputStreamStruct (), null, &error); throwGError (error, "Failed to load image data"); } ~this () { if (pix !is null) g_object_unref (pix); } @property uint width () { return pix.gdk_pixbuf_get_width (); } @property uint height () { return pix.gdk_pixbuf_get_height (); } /** * Scale the image to the given size. */ void scale (uint newWidth, uint newHeight) { auto resPix = gdk_pixbuf_scale_simple (pix, newWidth, newHeight, GdkInterpType.BILINEAR); if (resPix is null) throw new Exception (format ("Scaling of image to %sx%s failed.", newWidth, newHeight)); // set our current image to the scaled version g_object_unref (pix); pix = resPix; } /** * Scale the image to the given width, preserving * its aspect ratio. */ void scaleToWidth (uint newWidth) { import std.math; float scaleFactor = cast(float) newWidth / cast (float) width; uint newHeight = to!uint (floor (height * scaleFactor)); scale (newWidth, newHeight); } /** * Scale the image to the given height, preserving * its aspect ratio. */ void scaleToHeight (uint newHeight) { import std.math; float scaleFactor = cast(float) newHeight / cast(float) height; uint newWidth = to!uint (floor (width * scaleFactor)); scale (newWidth, newHeight); } /** * Scale the image to fir in a square with the given edge length, * and keep its aspect ratio. */ void scaleToFit (uint size) { if (height > width) { scaleToHeight (size); } else { scaleToWidth (size); } } void savePng (string fname) { GError *error = null; gdk_pixbuf_save (pix, fname.toStringz (), "png", &error, null); throwGError (error); optimizePNG (fname); } } final class Canvas { private: cairo_surface_p srf; cairo_p cr; int width_; int height_; public: this (int w, int h) { srf = cairo_image_surface_create (cairo_format_t.FORMAT_ARGB32, w, h); cr = cairo_create (srf); width_ = w; height_ = h; } ~this () { if (cr !is null) cairo_destroy (cr); if (srf !is null) cairo_surface_destroy (srf); } @property uint width () { return width_; //! return srf.cairo_image_surface_get_width (); } @property uint height () { return height_; //! return srf.cairo_image_surface_get_height (); } void renderSvg (ubyte[] svgBytes) { // NOTE: unfortunately, Cairo/RSvg uses Fontconfig internally, so // we need to lock this down since a parallel-processed font // might need to access this too. // This can likely be optimized by checking whether it's really // a Font that is holding the lock (= make only fonts increase the // Mutex counter) enterFontconfigCriticalSection (); auto handle = rsvg_handle_new (); scope (exit) { g_object_unref (handle); leaveFontconfigCriticalSection (); } auto svgBSize = ubyte.sizeof * svgBytes.length; GError *error = null; rsvg_handle_write (handle, cast(ubyte*) svgBytes, svgBSize, &error); if (error !is null) { auto msg = fromStringz (error.message).dup; g_error_free (error); throw new Exception (to!string (msg)); } rsvg_handle_close (handle, &error); if (error !is null) { auto msg = fromStringz (error.message).dup; g_error_free (error); throw new Exception (to!string (msg)); } RsvgDimensionData dims; rsvg_handle_get_dimensions (handle, &dims); auto w = cast(double) cairo_image_surface_get_width (srf); auto h = cast(double) cairo_image_surface_get_height (srf); // cairo_translate (cr, (w - dims.width) / 2, (h - dims.height) / 2); cairo_scale (cr, w / dims.width, h / dims.height); cr.cairo_save (); scope (exit) cr.cairo_restore (); if (!rsvg_handle_render_cairo (handle, cr)) throw new Exception ("Rendering of SVG images failed!"); } /** * Draw a simple line of text without linebreaks to fill the canvas. **/ void drawTextLine (const ref Font font, string text, uint borderWidth = 4) { import asgen.bindings.freetype : FT_LOAD_DEFAULT; enterFontconfigCriticalSection (); scope (exit) leaveFontconfigCriticalSection (); auto cff = cairo_ft_font_face_create_for_ft_face (font.fontFace, FT_LOAD_DEFAULT); scope (exit) cairo_font_face_destroy (cff); // set font face for Cairo surface auto status = cairo_font_face_status (cff); if (status != cairo_status_t.STATUS_SUCCESS) throw new Exception ("Could not set font face for Cairo: %s".format (to!string (status))); cairo_set_font_face (cr, cff); cairo_text_extents_t te; uint textSize = 128; while (textSize-- > 0) { cairo_set_font_size (cr, textSize); cairo_text_extents (cr, text.toStringz, &te); if (te.width <= 0.01f || te.height <= 0.01f) continue; if (te.width < this.width - (borderWidth * 2) && te.height < this.height - (borderWidth * 2)) break; } // draw text cairo_move_to (cr, (this.width / 2) - te.width / 2 - te.x_bearing, (this.height / 2) - te.height / 2 - te.y_bearing); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); cairo_show_text (cr, text.toStringz); cairo_save (cr); } /** * Draw a longer text with linebreaks. */ void drawText (const ref Font font, string text, const uint borderWidth = 4, const uint linePad = 2) { import asgen.bindings.freetype : FT_LOAD_DEFAULT; enterFontconfigCriticalSection (); scope (exit) leaveFontconfigCriticalSection (); auto cff = cairo_ft_font_face_create_for_ft_face (font.fontFace, FT_LOAD_DEFAULT); scope (exit) cairo_font_face_destroy (cff); // set font face for Cairo surface auto status = cairo_font_face_status (cff); if (status != cairo_status_t.STATUS_SUCCESS) throw new Exception (format ("Could not set font face for Cairo: %s", to!string (status))); cairo_set_font_face (cr, cff); // calculate best font size uint linePadding = linePad; auto lines = text.split ("\n"); string longestLine; if (lines.length <= 1) { linePadding = 0; longestLine = text; } else { ulong ll = 0; longestLine = lines[0]; foreach (line; lines) { if (line.length > ll) longestLine = line; ll = line.length; } } cairo_text_extents_t te; uint text_size = 128; while (text_size-- > 0) { cairo_set_font_size (cr, text_size); cairo_text_extents (cr, longestLine.toStringz, &te); if (te.width <= 0.01f || te.height <= 0.01f) continue; if (te.width < this.width - (borderWidth * 2) && (te.height * lines.length + linePadding) < this.height - (borderWidth * 2)) break; } // center text and draw it auto xPos = (this.width / 2) - te.width / 2 - te.x_bearing; auto teHeight = te.height * lines.length + linePadding * (lines.length-1); auto yPos = (teHeight / 2) - teHeight / 2 - te.y_bearing + borderWidth; cairo_move_to (cr, xPos, yPos); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); foreach (line; lines) { cairo_show_text (cr, line.toStringz ()); yPos += te.height + linePadding; cairo_move_to (cr, xPos, yPos); } cairo_save (cr); } void savePng (string fname) { auto status = cairo_surface_write_to_png (srf, fname.toStringz ()); if (status != cairo_status_t.STATUS_SUCCESS) throw new Exception (format ("Could not save canvas to PNG: %s", to!string (status))); optimizePNG (fname); } } unittest { import std.file : getcwd; import std.path : buildPath; import asgen.utils : getTestSamplesDir; writeln ("TEST: ", "Image"); auto sampleImgPath = buildPath (getTestSamplesDir (), "appstream-logo.png"); writeln ("Loading image (file)"); auto img = new Image (sampleImgPath); writeln ("Scaling image"); assert (img.width == 134); assert (img.height == 132); img.scale (64, 64); assert (img.width == 64); assert (img.height == 64); writeln ("Storing image"); img.savePng ("/tmp/ag-iscale_test.png"); writeln ("Loading image (data)"); ubyte[] data; auto f = File (sampleImgPath, "r"); while (!f.eof) { char[300] buf; data ~= f.rawRead (buf); } img = new Image (data, ImageFormat.PNG); writeln ("Scaling image (data)"); img.scale (124, 124); writeln ("Storing image (data)"); img.savePng ("/tmp/ag-iscale-d_test.png"); writeln ("Rendering SVG"); auto sampleSvgPath = buildPath (getTestSamplesDir (), "table.svgz"); data = null; f = File (sampleSvgPath, "r"); while (!f.eof) { char[300] buf; data ~= f.rawRead (buf); } auto cv = new Canvas (512, 512); cv.renderSvg (data); writeln ("Saving rendered PNG"); cv.savePng ("/tmp/ag-svgrender_test1.png"); writeln ("Font rendering"); auto font = new Font (buildPath (getTestSamplesDir (), "NotoSans-Regular.ttf")); cv = new Canvas (400, 100); cv.drawText (font, "Hello World!\nSecond Line!\nThird line - äöüß!\nA very, very, very long line."); cv.savePng ("/tmp/ag-fontrender_test1.png"); } appstream-generator-0.6.8/src/asgen/logging.d000066400000000000000000000037601320016272000211630ustar00rootroot00000000000000/* * Copyright (C) 2016 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.logging; import std.stdio; import std.string : format; import std.datetime; private __gshared bool __verbose = false; enum LogSeverity : string { DEBUG = "DEBUG", INFO = "INFO", WARNING = "WARNING", ERROR = "ERROR" } @trusted void logMessage (LogSeverity, string, Args...) (const LogSeverity severity, const string tmpl, const Args args) { auto time = Clock.currTime (); auto timeStr = "%d-%02d-%02d %02d:%02d:%02d".format (time.year, time.month, time.day, time.hour,time.minute, time.second); writeln (timeStr, " - ", severity, ": ", format (tmpl, args)); } @trusted void logDebug (string, Args...) (const string tmpl, const Args args) { if (__verbose) logMessage (LogSeverity.DEBUG, tmpl, args); } @safe void logInfo (string, Args...) (const string tmpl, const Args args) { logMessage (LogSeverity.INFO, tmpl, args); } @safe void logWarning (string, Args...) (const string tmpl, const Args args) { logMessage (LogSeverity.WARNING, tmpl, args); } @safe void logError (string, Args...) (const string tmpl, const Args args) { logMessage (LogSeverity.ERROR, tmpl, args); } @trusted void setVerbose (const bool enabled) { __verbose = enabled; } appstream-generator-0.6.8/src/asgen/meson.build000066400000000000000000000004441320016272000215260ustar00rootroot00000000000000 conf_data = configuration_data() conf_data.set('datadir', join_paths(get_option('prefix'), get_option('datadir'), 'appstream')) conf_data.set('asgen_version', asgen_version) configure_file(input : 'defines.d.in', output: 'defines.d', configuration: conf_data ) appstream-generator-0.6.8/src/asgen/reportgenerator.d000066400000000000000000000712661320016272000227650ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.reportgenerator; import std.stdio; import std.string; import std.parallelism; import std.path : buildPath, buildNormalizedPath, dirName; import std.file : mkdirRecurse, rmdirRecurse; import std.array : empty; import std.json; import std.conv : to; import std.typecons : scoped; static import std.file; import mustache; import appstream.Metadata; import asgen.defines : ASGEN_VERSION; import asgen.utils; import asgen.config; import asgen.logging; import asgen.hint; import asgen.backends.interfaces; import asgen.datastore; private alias MustacheEngine!(string) Mustache; final class ReportGenerator { private: Config conf; PackageIndex pkgIndex; DataStore dstore; string htmlExportDir; string templateDir; string defaultTemplateDir; string mediaPoolDir; string mediaPoolUrl; string versionInfo; Mustache mustache; struct HintTag { string tag; string message; } struct HintEntry { string identifier; string[] archs; HintTag[] errors; HintTag[] warnings; HintTag[] infos; } struct MetadataEntry { ComponentKind kind; string identifier; string[] archs; string data; string iconName; } struct PkgSummary { string pkgname; string[] cpts; int infoCount; int warningCount; int errorCount; } struct DataSummary { PkgSummary[string][string] pkgSummaries; HintEntry[string][string] hintEntries; MetadataEntry[string][string][string] mdataEntries; // package -> version -> gcid -> entry long totalMetadata; long totalInfos; long totalWarnings; long totalErrors; } public: this (DataStore db) { this.conf = Config.get (); // we need the data store to get hint and metainfo data dstore = db; htmlExportDir = conf.htmlExportDir; mediaPoolDir = dstore.mediaExportPoolDir; mediaPoolUrl = buildPath (conf.mediaBaseUrl, "pool"); // get template directory templateDir = conf.templateDir; defaultTemplateDir = buildNormalizedPath (templateDir, "..", "default"); mustache.path = templateDir; mustache.ext = "html"; // create version information to display on every page import asgen.bindings.appstream_utils : as_get_appstream_version; import std.string : fromStringz; versionInfo = "%s, AS: %s".format (ASGEN_VERSION, as_get_appstream_version.fromStringz); } private string[] splitBlockData (string str, string blockType) { auto content = str.strip (); string blockName; if (content.startsWith ("{")) { auto li = content.indexOf("}"); if (li <= 0) throw new Exception ("Invalid %s: Closing '}' missing.", blockType); blockName = content[1..li].strip (); if (li+1 >= content.length) content = ""; else content = content[li+1..$]; } if (blockName is null) throw new Exception ("Invalid %s: Does not have a name.", blockType); return [blockName, content]; } private void setupMustacheContext (Mustache.Context context) { import std.datetime : Clock; string[string] partials; // this implements a very cheap way to get template inheritance // would obviously be better if our template system supported this natively. context["partial"] = (string str) { auto split = splitBlockData (str, "partial"); partials[split[0]] = split[1]; return ""; }; context["block"] = (string str) { auto split = splitBlockData (str, "block"); auto blockName = split[0]; str = split[1] ~ "\n"; auto partialCP = (blockName in partials); if (partialCP is null) return str; else return *partialCP; }; auto time = Clock.currTime (); auto timeStr = "%d-%02d-%02d %02d:%02d [%s]".format (time.year, time.month, time.day, time.hour,time.minute, time.timezone.stdName); context["time"] = timeStr; context["generator_version"] = versionInfo; context["project_name"] = conf.projectName; context["root_url"] = conf.htmlBaseUrl; } private void renderPage (string pageID, string exportName, Mustache.Context context) { setupMustacheContext (context); auto fname = buildPath (htmlExportDir, exportName) ~ ".html"; std.file.mkdirRecurse (dirName (fname)); if (!std.file.exists (buildPath (templateDir, pageID ~ ".html"))) { if (std.file.exists (buildPath (defaultTemplateDir, pageID ~ ".html"))) mustache.path = defaultTemplateDir; } logDebug ("Rendering HTML page: %s", exportName); auto data = mustache.render (pageID, context).strip (); auto f = File (fname, "w"); f.writeln (data); // reset default template path, we might have changed it mustache.path = templateDir; } private void renderPagesFor (string suiteName, string section, DataSummary dsum) { static import std.regex; if (templateDir is null) { logError ("Can not render HTML: No page templates found."); return; } logInfo ("Rendering HTML for %s/%s", suiteName, section); auto maintRE = std.regex.ctRegex!(`[àáèéëêòöøîìùñ~/\\(\\)" ']`, "g"); // write issue hint pages foreach (ref pkgname; dsum.hintEntries.byKey ()) { auto pkgHEntries = dsum.hintEntries[pkgname]; auto exportName = format ("%s/%s/issues/%s", suiteName, section, pkgname); auto context = new Mustache.Context; context["suite"] = suiteName; context["package_name"] = pkgname; context["section"] = section; context["entries"] = (string content) { string res; foreach (ref cid; pkgHEntries.byKey ()) { auto hentry = pkgHEntries[cid]; auto intCtx = new Mustache.Context; intCtx["component_id"] = cid; foreach (arch; hentry.archs) { auto archSub = intCtx.addSubContext("architectures"); archSub["arch"] = arch; } if (!hentry.errors.empty) intCtx["has_errors"] = ["has_errors": "yes"]; foreach (error; hentry.errors) { auto errSub = intCtx.addSubContext("errors"); errSub["error_tag"] = error.tag; errSub["error_description"] = error.message; } if (!hentry.warnings.empty) intCtx["has_warnings"] = ["has_warnings": "yes"]; foreach (warning; hentry.warnings) { auto warnSub = intCtx.addSubContext("warnings"); warnSub["warning_tag"] = warning.tag; warnSub["warning_description"] = warning.message; } if (!hentry.infos.empty) intCtx["has_infos"] = ["has_infos": "yes"]; foreach (info; hentry.infos) { auto infoSub = intCtx.addSubContext("infos"); infoSub["info_tag"] = info.tag; infoSub["info_description"] = info.message; } res ~= mustache.renderString (content, intCtx); } return res; }; renderPage ("issues_page", exportName, context); } // write metadata info pages foreach (ref pkgname; dsum.mdataEntries.byKey ()) { auto pkgMVerEntries = dsum.mdataEntries[pkgname]; auto exportName = format ("%s/%s/metainfo/%s", suiteName, section, pkgname); auto context = new Mustache.Context; context["suite"] = suiteName; context["package_name"] = pkgname; context["section"] = section; context["cpts"] = (string content) { string res; foreach (ver; pkgMVerEntries.byKey ()) { auto mEntries = pkgMVerEntries[ver]; foreach (gcid; mEntries.byKey ()) { auto mentry = mEntries[gcid]; auto intCtx = new Mustache.Context; intCtx["component_id"] = format ("%s - %s", mentry.identifier, ver); foreach (arch; mentry.archs) { auto archSub = intCtx.addSubContext("architectures"); archSub["arch"] = arch; } intCtx["metadata"] = mentry.data; auto cptMediaPath = buildPath (mediaPoolDir, gcid); auto cptMediaUrl = buildPath (mediaPoolUrl, gcid); string iconUrl; switch (mentry.kind) { case ComponentKind.UNKNOWN: iconUrl = buildPath (conf.htmlBaseUrl, "static", "img", "no-image.png"); break; case ComponentKind.DESKTOP_APP: case ComponentKind.WEB_APP: case ComponentKind.FONT: if (std.file.exists (buildPath (cptMediaPath, "icons", "64x64", mentry.iconName))) iconUrl = buildPath (cptMediaUrl, "icons", "64x64", mentry.iconName); else iconUrl = buildPath (conf.htmlBaseUrl, "static", "img", "no-image.png"); break; default: iconUrl = buildPath (conf.htmlBaseUrl, "static", "img", "cpt-nogui.png"); break; } intCtx["icon_url"] = iconUrl; res ~= mustache.renderString (content, intCtx); } } return res; }; renderPage ("metainfo_page", exportName, context); } // write hint overview page auto hindexExportName = format ("%s/%s/issues/index", suiteName, section); auto hsummaryCtx = new Mustache.Context; hsummaryCtx["suite"] = suiteName; hsummaryCtx["section"] = section; hsummaryCtx["summaries"] = (string content) { string res; foreach (maintainer; dsum.pkgSummaries.byKey ()) { auto summaries = dsum.pkgSummaries[maintainer]; auto intCtx = new Mustache.Context; intCtx["maintainer"] = maintainer; intCtx["maintainer_anchor"] = std.regex.replaceAll (maintainer, maintRE, "_"); bool interesting = false; foreach (summary; summaries.byValue ()) { if ((summary.infoCount == 0) && (summary.warningCount == 0) && (summary.errorCount == 0)) continue; interesting = true; auto maintSub = intCtx.addSubContext("packages"); maintSub["pkgname"] = summary.pkgname; // again, we use this dumb hack to allow conditionals in the Mustache // template. if (summary.infoCount > 0) maintSub["has_info_count"] =["has_count": "yes"]; if (summary.warningCount > 0) maintSub["has_warning_count"] =["has_count": "yes"]; if (summary.errorCount > 0) maintSub["has_error_count"] =["has_count": "yes"]; maintSub["info_count"] = summary.infoCount; maintSub["warning_count"] = summary.warningCount; maintSub["error_count"] = summary.errorCount; } if (interesting) res ~= mustache.renderString (content, intCtx); } return res; }; renderPage ("issues_index", hindexExportName, hsummaryCtx); // write metainfo overview page auto mindexExportName = format ("%s/%s/metainfo/index", suiteName, section); auto msummaryCtx = new Mustache.Context; msummaryCtx["suite"] = suiteName; msummaryCtx["section"] = section; msummaryCtx["summaries"] = (string content) { string res; foreach (maintainer; dsum.pkgSummaries.byKey ()) { auto summaries = dsum.pkgSummaries[maintainer]; auto intCtx = new Mustache.Context; intCtx["maintainer"] = maintainer; intCtx["maintainer_anchor"] = std.regex.replaceAll (maintainer, maintRE, "_"); intCtx["packages"] = (string content) { string res; foreach (summary; summaries) { if (summary.cpts.length == 0) continue; auto subCtx = new Mustache.Context; subCtx["pkgname"] = summary.pkgname; foreach (cid; summary.cpts) { auto cptsSub = subCtx.addSubContext("components"); cptsSub["cid"] = cid; } res ~= mustache.renderString (content, subCtx); } return res; }; res ~= mustache.renderString (content, intCtx); } return res; }; renderPage ("metainfo_index", mindexExportName, msummaryCtx); // render section index page auto secIndexExportName = format ("%s/%s/index", suiteName, section); auto secIndexCtx = new Mustache.Context; secIndexCtx["suite"] = suiteName; secIndexCtx["section"] = section; float percOne = 100.0 / cast(float) (dsum.totalMetadata + dsum.totalInfos + dsum.totalWarnings + dsum.totalErrors); secIndexCtx["valid_percentage"] = dsum.totalMetadata * percOne; secIndexCtx["info_percentage"] = dsum.totalInfos * percOne; secIndexCtx["warning_percentage"] = dsum.totalWarnings * percOne; secIndexCtx["error_percentage"] = dsum.totalErrors * percOne; secIndexCtx["metainfo_count"] = dsum.totalMetadata; secIndexCtx["error_count"] = dsum.totalErrors; secIndexCtx["warning_count"] = dsum.totalWarnings; secIndexCtx["info_count"] = dsum.totalInfos; renderPage ("section_page", secIndexExportName, secIndexCtx); } private DataSummary preprocessInformation (string suiteName, string section, Package[] pkgs) { DataSummary dsum; logInfo ("Collecting data about hints and available metainfo for %s/%s", suiteName, section); auto hintstore = HintsStorage.get (); auto dtype = conf.metadataType; auto mdata = scoped!Metadata (); mdata.setFormatStyle (FormatStyle.COLLECTION); mdata.setFormatVersion (conf.formatVersion); foreach (ref pkg; pkgs) { immutable pkid = pkg.id; auto gcids = dstore.getGCIDsForPackage (pkid); auto hintsData = dstore.getHints (pkid); if ((hintsData is null) && (gcids is null)) continue; PkgSummary pkgsummary; bool newInfo = false; pkgsummary.pkgname = pkg.name; if (pkg.maintainer in dsum.pkgSummaries) { auto pkgSumP = pkg.name in dsum.pkgSummaries[pkg.maintainer]; if (pkgSumP !is null) pkgsummary = *pkgSumP; else newInfo = true; } // process component metadata for this package if there are any if (gcids !is null) { foreach (gcid; gcids) { auto cid = getCidFromGlobalID (gcid); // don't add the same entry multiple times for multiple versions if (pkg.name in dsum.mdataEntries) { if (pkg.ver in dsum.mdataEntries[pkg.name]) { auto meP = gcid in dsum.mdataEntries[pkg.name][pkg.ver]; if (meP is null) { // this component is new dsum.totalMetadata += 1; newInfo = true; } else { // we already have a component with this gcid (*meP).archs ~= pkg.arch; continue; } } } else { // we will add a new component dsum.totalMetadata += 1; } MetadataEntry me; me.identifier = cid; me.data = dstore.getMetadata (dtype, gcid); mdata.clearComponents (); if (dtype == DataType.YAML) mdata.parse (me.data, FormatKind.YAML); else mdata.parse (me.data, FormatKind.XML); auto cpt = mdata.getComponent (); if (cpt !is null) { auto iconsArr = cpt.getIcons (); for (uint i = 0; i < iconsArr.len; i++) { import appstream.Icon; auto icon = scoped!Icon (cast (AsIcon*) iconsArr.index (i)); if (icon.getKind () == IconKind.CACHED) { me.iconName = icon.getName (); break; } } me.kind = cpt.getKind (); } else { me.kind = ComponentKind.UNKNOWN; } me.archs ~= pkg.arch; dsum.mdataEntries[pkg.name][pkg.ver][gcid] = me; pkgsummary.cpts ~= format ("%s - %s", cid, pkg.ver); } } // process hints for this package, if there are any if (hintsData !is null) { auto hintsCpts = parseJSON (hintsData); hintsCpts = hintsCpts["hints"]; foreach (cid; hintsCpts.object.byKey ()) { auto jhints = hintsCpts[cid]; HintEntry he; // don't add the same hints multiple times for multiple versions and architectures if (pkg.name in dsum.hintEntries) { auto heP = cid in dsum.hintEntries[pkg.name]; if (heP !is null) { he = *heP; // we already have hints for this component ID he.archs ~= pkg.arch; // TODO: check if we have the same hints - if not, create a new entry. continue; } newInfo = true; } else { newInfo = true; } he.identifier = cid; foreach (jhint; jhints.array) { auto tag = jhint["tag"].str; auto hdef = hintstore.getHintDef (tag); if (hdef.tag is null) { logError ("Encountered invalid tag '%s' in component '%s' of package '%s'", tag, cid, pkid); // emit an internal error, invalid tags shouldn't happen hdef = hintstore.getHintDef ("internal-unknown-tag"); assert (hdef.tag !is null); jhint["vars"] = ["tag": tag]; } // render the full message using the static template and data from the hint auto context = new Mustache.Context; foreach (var; jhint["vars"].object.byKey ()) { context[var] = jhint["vars"][var].str; } auto msg = mustache.renderString (hdef.text, context); // add the new hint to the right category auto severity = hintstore.getSeverity (tag); if (severity == HintSeverity.INFO) { he.infos ~= HintTag (tag, msg); pkgsummary.infoCount++; } else if (severity == HintSeverity.WARNING) { he.warnings ~= HintTag (tag, msg); pkgsummary.warningCount++; } else { he.errors ~= HintTag (tag, msg); pkgsummary.errorCount++; } } if (newInfo) he.archs ~= pkg.arch; dsum.hintEntries[pkg.name][he.identifier] = he; } } dsum.pkgSummaries[pkg.maintainer][pkg.name] = pkgsummary; if (newInfo) { dsum.totalInfos += pkgsummary.infoCount; dsum.totalWarnings += pkgsummary.warningCount; dsum.totalErrors += pkgsummary.errorCount; } } // rehash the tables for slightly better performance dsum.hintEntries.rehash; dsum.mdataEntries.rehash; dsum.pkgSummaries.rehash; return dsum; } private void saveStatistics (string suiteName, string section, DataSummary dsum) { auto stat = JSONValue (["suite": JSONValue (suiteName), "section": JSONValue (section), "totalInfos": JSONValue (dsum.totalInfos), "totalWarnings": JSONValue (dsum.totalWarnings), "totalErrors": JSONValue (dsum.totalErrors), "totalMetadata": JSONValue (dsum.totalMetadata)]); dstore.addStatistics (stat); } void exportStatistics () { import std.algorithm : sort; logInfo ("Exporting statistical data."); // return all statistics we have from the database auto statsCollection = dstore.getStatistics (); auto emptyJsonObject () { auto jobj = JSONValue (["null": 0]); jobj.object.remove ("null"); return jobj; } auto emptyJsonArray () { auto jarr = JSONValue ([0, 0]); jarr.array = []; return jarr; } // create JSON for use with e.g. Rickshaw graph auto smap = emptyJsonObject (); foreach (ref entry; statsCollection) { auto js = entry.data; immutable timestamp = entry.time; JSONValue jstats; if (js.type == JSON_TYPE.ARRAY) jstats = js; else jstats = JSONValue ([js]); foreach (ref jvals; jstats.array) { auto suite = jvals["suite"].str; auto section = jvals["section"].str; if (suite !in smap) smap.object[suite] = emptyJsonObject (); if (section !in smap[suite]) { smap[suite].object[section] = emptyJsonObject (); auto sso = smap[suite][section].object; sso["errors"] = emptyJsonArray (); sso["warnings"] = emptyJsonArray (); sso["infos"] = emptyJsonArray (); sso["metadata"] = emptyJsonArray (); } auto suiteSectionObj = smap[suite][section].object; auto pointErr = JSONValue ([JSONValue (timestamp), JSONValue (jvals["totalErrors"])]); suiteSectionObj["errors"].array ~= pointErr; auto pointWarn = JSONValue ([JSONValue (timestamp), JSONValue (jvals["totalWarnings"])]); suiteSectionObj["warnings"].array ~= pointWarn; auto pointInfo = JSONValue ([JSONValue (timestamp), JSONValue (jvals["totalInfos"])]); suiteSectionObj["infos"].array ~= pointInfo; auto pointMD = JSONValue ([JSONValue (timestamp), JSONValue (jvals["totalMetadata"])]); suiteSectionObj["metadata"].array ~= pointMD; } } bool compareJData (JSONValue x, JSONValue y) @trusted { size_t xv; size_t yv; if (x.array[0].type == JSON_TYPE.UINTEGER) xv = to!size_t (x.array[0].uinteger); else xv = to!size_t (x.array[0].integer); if (y.array[0].type == JSON_TYPE.UINTEGER) yv = to!size_t (y.array[0].uinteger); else yv = to!size_t (y.array[0].integer); return xv < yv; } // ensure our data is sorted ascending by X foreach (suite; smap.object.byKey ()) { foreach (section; smap[suite].object.byKey ()) { auto sso = smap[suite][section].object; sort!(compareJData) (sso["errors"].array); sort!(compareJData) (sso["warnings"].array); sort!(compareJData) (sso["infos"].array); sort!(compareJData) (sso["metadata"].array); } } auto fname = buildPath (htmlExportDir, "statistics.json"); mkdirRecurse (dirName (fname)); auto sf = File (fname, "w"); sf.writeln (smap.toJSON (false)); sf.flush (); sf.close (); } void processFor (string suiteName, string section, Package[] pkgs) { // collect all needed information and save statistics auto dsum = preprocessInformation (suiteName, section, pkgs); saveStatistics (suiteName, section, dsum); // drop old pages auto suitSecPagesDest = buildPath (htmlExportDir, suiteName, section); if (std.file.exists (suitSecPagesDest)) rmdirRecurse (suitSecPagesDest); // render fresh info pages renderPagesFor (suiteName, section, dsum); } void updateIndexPages () { import std.algorithm : sort; logInfo ("Updating HTML index pages and static data."); // render main overview auto context = new Mustache.Context; foreach (suite; conf.suites.sort!("a.name < b.name")) { auto sub = context.addSubContext("suites"); sub["suite"] = suite.name; auto secCtx = new Mustache.Context; secCtx["suite"] = suite.name; foreach (section; suite.sections) { auto secSub = secCtx.addSubContext("sections"); secSub["section"] = section; } renderPage ("sections_index", format ("%s/index", suite.name), secCtx); } foreach (suite; conf.oldsuites.sort!("a < b")) { auto sub = context.addSubContext("oldsuites"); sub["suite"] = suite; } renderPage ("main", "index", context); // copy static data, if present auto staticSrcDir = buildPath (templateDir, "static"); if (std.file.exists (staticSrcDir)) { auto staticDestDir = buildPath (htmlExportDir, "static"); if (std.file.exists (staticDestDir)) rmdirRecurse (staticDestDir); copyDir (staticSrcDir, staticDestDir); } } } unittest { writeln ("TEST: ", "Report Generator"); //auto rg = new ReportGenerator (null); //rg.renderIndices (); } appstream-generator-0.6.8/src/asgen/result.d000066400000000000000000000252041320016272000210500ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.result; import std.stdio; import std.string; import std.array : empty; import std.conv : to; import std.json; import appstream.Component; import asgen.hint; import asgen.utils : buildCptGlobalID; import asgen.backends.interfaces; import asgen.config : Config; /** * Helper function for GeneratorResult.finalize() */ extern(C) int evaluateCustomEntry (void *keyPtr, void *value, void *userData) { auto key = (cast(const(char)*) keyPtr).fromStringz; auto conf = *cast(Config*) userData; if (key in conf.allowedCustomKeys) return false; // FALSE, do not delete // remove invalid key return true; } final class GeneratorResult { private: Component[string] cpts; string[Component] cptGCID; string[string] mdataHashes; HintList[string] hints; public: immutable string pkid; immutable string pkgname; Package pkg; public: this (Package pkg) { this.pkid = pkg.id; this.pkgname = pkg.name; this.pkg = pkg; } @safe bool packageIsIgnored () pure { return (cpts.length == 0) && (hints.length == 0); } @safe Component getComponent (string id) pure { auto ptr = (id in cpts); if (ptr is null) return null; return *ptr; } @trusted Component[] getComponents () pure { return cpts.values (); } @trusted bool isIgnored (Component cpt) { return getComponent (cpt.getId ()) is null; } @trusted void updateComponentGCID (Component cpt, string data) { import std.digest.md; auto cid = cpt.getId (); if (data.empty) { cptGCID[cpt] = buildCptGlobalID (cid, "???-NO_CHECKSUM-???"); return; } auto oldHashP = (cid in mdataHashes); string oldHash = ""; if (oldHashP !is null) oldHash = *oldHashP; auto hash = md5Of (oldHash ~ data); auto checksum = toHexString (hash); auto newHash = to!string (checksum); mdataHashes[cid] = newHash; cptGCID[cpt] = buildCptGlobalID (cid, newHash); } @trusted void addComponent (Component cpt, string data = "") { string cid = cpt.getId; if (cid.empty) throw new Exception ("Can not add component from '%s' without ID to results set: %s".format (this.pkid, cpt.toString)); // web applications don't have a package name set if (cpt.getKind != ComponentKind.WEB_APP) cpt.setPkgnames ([this.pkgname]); cpts[cid] = cpt; updateComponentGCID (cpt, data); } @safe void dropComponent (string cid) pure { auto cpt = getComponent (cid); if (cpt is null) return; cpts.remove (cid); cptGCID.remove (cpt); } /** * Add an issue hint to this result. * Params: * id = The component-id or component itself this tag is assigned to. * tag = The hint tag. * params = Dictionary of parameters to insert into the issue report. * Returns: * True if the hint did not cause the removal of the component, False otherwise. **/ @trusted bool addHint (T) (T id, string tag, string[string] params) if (is(T == string) || is(T == Component) || is(T == typeof(null))) { static if (is(T == string)) { immutable cid = id; } else { static if (is(T == typeof(null))) immutable cid = "general"; else immutable cid = id.getId (); } auto hint = new GeneratorHint (tag, cid); hint.setVars (params); hints[cid] ~= hint; // we stop dealing with this component when we encounter a fatal // error. if (hint.isError) { dropComponent (cid); return false; } return true; } /** * Add an issue hint to this result. * Params: * id = The component-id or component itself this tag is assigned to. * tag = The hint tag. * msg = An error message to add to the report. * Returns: * True if the hint did not cause the removal of the component, False otherwise. **/ @safe bool addHint (T) (T id, string tag, string msg = null) { string[string] vars; if (msg !is null) vars = ["msg": msg]; return addHint (id, tag, vars); } /** * Create JSON metadata for the hints found for the package * associacted with this GeneratorResult. */ string hintsToJson () { if (hints.length == 0) return null; // is this really the only way you can set a type for JSONValue? auto map = JSONValue (["null": 0]); map.object.remove ("null"); foreach (cid; hints.byKey ()) { auto cptHints = hints[cid]; auto hintNodes = JSONValue ([0, 0]); hintNodes.array = []; foreach (GeneratorHint hint; cptHints) { hintNodes.array ~= hint.toJsonNode (); } map.object[cid] = hintNodes; } auto root = JSONValue (["package": JSONValue (pkid), "hints": map]); return root.toJSON (true); } /** * Drop invalid components and components with errors. */ void finalize () { auto conf = Config.get (); // we need to duplicate the associative array, because the addHint() function // may remove entries from "cpts", breaking our foreach loop. foreach (cpt; cpts.dup.byValue) { auto ckind = cpt.getKind; cpt.setActiveLocale ("C"); if (ckind == ComponentKind.UNKNOWN) if (!addHint (cpt, "metainfo-unknown-type")) continue; if ((!cpt.hasBundle) && (cpt.getPkgnames.empty) && (ckind != ComponentKind.WEB_APP)) if (!addHint (cpt, "no-install-candidate")) continue; if (cpt.getName.empty) if (!addHint (cpt, "metainfo-no-name")) continue; if (cpt.getSummary.empty) if (!addHint (cpt, "metainfo-no-summary")) continue; // desktop apps get extra treatment (more validation, addition of fallback long-description) if (ckind == ComponentKind.DESKTOP_APP) { // checks specific for .desktop and web apps if (cpt.getIcons ().len == 0) if (!addHint (cpt, "gui-app-without-icon")) continue; // desktop-application components are required to have a category if (cpt.getCategories ().len <= 0) if (!addHint (cpt, "no-valid-category")) continue; // inject package descriptions, if needed auto flags = cpt.getValueFlags; cpt.setValueFlags (flags | AsValueFlags.NO_TRANSLATION_FALLBACK); cpt.setActiveLocale ("C"); if (cpt.getDescription.empty) { // component doesn't have a long description, add one from // the packaging. auto desc_added = false; foreach (ref lang, ref desc; pkg.description) { cpt.setDescription (desc, lang); desc_added = true; } if (desc_added) if (!addHint (cpt, "description-from-package")) continue; } // check if we can add a launchable here if ((cpt.getLaunchable (LaunchableKind.DESKTOP_ID) is null) && (cpt.getId.endsWith (".desktop"))) { import appstream.Launchable; auto launch = new Launchable; launch.setKind (LaunchableKind.DESKTOP_ID); launch.addEntry (cpt.getId ()); cpt.addLaunchable (launch); } } // finally, filter custom tags auto customHashTable = cpt.getCustom (); auto noCustomKeysAllowed = conf.allowedCustomKeys.length == 0; if (customHashTable.size > 0) { import glib.c.types; if (noCustomKeysAllowed) { // if we don't allow any custom keys, we can delete them faster customHashTable.removeAll (); continue; } // filter the custom values customHashTable.foreachRemove (&evaluateCustomEntry, &conf); } } } /** * Return the number of components we've found. **/ @safe ulong componentsCount () pure { return cpts.length; } /** * Return the number of hints that have been emitted. **/ @safe ulong hintsCount () pure { return hints.length; } @safe string gcidForComponent (Component cpt) pure { auto cgp = (cpt in cptGCID); if (cgp is null) return null; return *cgp; } @trusted string[] getGCIDs () pure { return cptGCID.values (); } } unittest { import asgen.backends.dummy.dummypkg; writeln ("TEST: ", "GeneratorResult"); auto pkg = new DummyPackage ("foobar", "1.0", "amd64"); auto res = new GeneratorResult (pkg); auto vars = ["rainbows": "yes", "unicorns": "no", "storage": "towel"]; res.addHint ("org.freedesktop.foobar.desktop", "just-a-unittest", vars); res.addHint ("org.freedesktop.awesome-bar.desktop", "metainfo-chocolate-missing", "Nothing is good without chocolate. Add some."); res.addHint ("org.freedesktop.awesome-bar.desktop", "metainfo-does-not-frobnicate", "Frobnicate functionality is missing."); writeln (res.hintsToJson ()); } appstream-generator-0.6.8/src/asgen/utils.d000066400000000000000000000351311320016272000206720ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.utils; @safe: import std.stdio : File, write, writeln; import std.string; import std.ascii : letters, digits; import std.conv : to; import std.random : randomSample; import std.range : chain; import std.algorithm : startsWith; import std.array : appender, empty; import std.path : buildPath, dirName, buildNormalizedPath; import std.typecons : Nullable; import std.datetime : Clock, parseRFC822DateTime, SysTime; static import std.file; import appstream.Component; import appstream.Icon; import asgen.logging; import asgen.defines; public immutable DESKTOP_GROUP = "Desktop Entry"; public immutable GENERIC_BUFFER_SIZE = 2048; struct ImageSize { uint width; uint height; uint scale; this (uint w, uint h, uint s) { width = w; height = h; scale = s; } this (uint w, uint h) { width = w; height = h; scale = 1; } this (uint s) { width = s; height = s; scale = 1; } string toString () const { if (scale == 1) return "%ux%u".format (width, height); else return "%ux%u@%u".format (width, height, scale); } uint toInt () const { if (width > height) return width * scale; return height * scale; } int opCmp (const ImageSize s) const { // only compares width, should be enough for now if (this.width > s.width) return 1; else if (this.width < s.width) return -1; if (this.scale > s.scale) return 1; else if (this.scale < s.scale) return -1; return 0; } } /** * Generate a random alphanumeric string. */ @trusted string randomString (uint len) { auto asciiLetters = to! (dchar[]) (letters); auto asciiDigits = to! (dchar[]) (digits); if (len == 0) len = 1; auto res = to!string (randomSample (chain (asciiLetters, asciiDigits), len)); return res; } /** * Check if the locale is a valid locale which we want to include * in the resulting metadata. Some locales added just for testing * by upstreams should be filtered out. */ @safe bool localeValid (string locale) pure { switch (locale) { case "x-test": case "xx": return false; default: return true; } } /** * Check if the given string is a top-level domain name. * The TLD list of AppStream is incomplete, but it will * cover 99% of all cases. * (in a short check on Debian, it covered all TLDs in use there) */ @trusted bool isTopLevelDomain (const string value) pure { import asgen.bindings.appstream_utils; if (value.empty) return false; return as_utils_is_tld (value.toStringz); } /** * Build a global component ID. * * The global-id is used as a global, unique identifier for this component. * (while the component-ID is local, e.g. for one suite). * Its primary usecase is to identify a media directory on the filesystem which is * associated with this component. **/ @trusted string buildCptGlobalID (string cid, string checksum, bool allowNoChecksum = false) pure in { assert (cid.length >= 2); } body { if (cid is null) return null; if ((!allowNoChecksum) && (checksum is null)) return null; if (checksum is null) checksum = ""; // check whether we can build the gcid by using the reverse domain name, // or whether we should use the simple standard splitter. auto reverseDomainSplit = false; immutable parts = cid.split ("."); if (parts.length > 2) { // check if we have a valid TLD. If so, use the reverse-domain-name splitting. if (isTopLevelDomain (parts[0])) reverseDomainSplit = true; } string gcid; if (reverseDomainSplit) gcid = "%s/%s/%s/%s".format (parts[0].toLower(), parts[1], join (parts[2..$], "."), checksum); else gcid = "%s/%s/%s/%s".format (cid[0].toLower(), cid[0..2].toLower(), cid, checksum); return gcid; } /** * Get the component-id back from a global component-id. */ @trusted string getCidFromGlobalID (string gcid) pure { import asgen.bindings.appstream_utils; auto parts = gcid.split ("/"); if (parts.length != 4) return null; if (isTopLevelDomain (parts[0])) { return join (parts[0..3], "."); } return parts[2]; } @trusted void hardlink (const string srcFname, const string destFname) { import core.sys.posix.unistd; import core.stdc.string; import core.stdc.errno; immutable res = link (srcFname.toStringz, destFname.toStringz); if (res != 0) throw new std.file.FileException ("Unable to create link: %s".format (errno.strerror)); } /** * Copy a directory using multiple threads. * This function follows symbolic links, * and replaces them with actual directories * in destDir. * * Params: * srcDir = Source directory to copy. * destDir = Path to the destination directory. * useHardlinks = Use hardlinks instead of copying files. */ void copyDir (in string srcDir, in string destDir, bool useHardlinks = false) @trusted { import std.file; import std.path; import std.parallelism; import std.array : appender; auto deSrc = DirEntry (srcDir); auto files = appender!(string[]); if (!exists (destDir)) { mkdirRecurse (destDir); } auto deDest = DirEntry (destDir); if(!deDest.isDir ()) { throw new FileException (deDest.name, " is not a directory"); } immutable destRoot = deDest.name ~ '/'; if (!deSrc.isDir ()) { if (useHardlinks) hardlink (deSrc.name, destRoot); else std.file.copy (deSrc.name, destRoot); } else { auto srcLen = deSrc.name.length; if (!std.file.exists (destRoot)) mkdir (destRoot); // make an array of the regular files and create the directory structure // Since it is SpanMode.breadth, we can just use mkdir foreach (DirEntry e; dirEntries (deSrc.name, SpanMode.breadth, true)) { if (attrIsDir (e.attributes)) { auto childDir = destRoot ~ e.name[srcLen..$]; mkdir (childDir); } else { files ~= e.name; } } // parallel foreach for regular files foreach (fn; taskPool.parallel (files.data, 100)) { immutable destFn = destRoot ~ fn[srcLen..$]; if (useHardlinks) hardlink (fn, destFn); else std.file.copy (fn, destFn); } } } /** * Escape XML characters. */ @safe S escapeXml (S) (S s) pure { string r; size_t lastI; auto result = appender!S (); foreach (i, c; s) { switch (c) { case '&': r = "&"; break; case '"': r = """; break; case '\'': r = "'"; break; case '<': r = "<"; break; case '>': r = ">"; break; default: continue; } // Replace with r result.put (s[lastI .. i]); result.put (r); lastI = i + 1; } if (!result.data.ptr) return s; result.put (s[lastI .. $]); return result.data; } /** * Get full path for an AppStream generator data file. */ @safe string getDataPath (string fname) { import std.path; auto resPath = buildPath (DATADIR, fname); if (std.file.exists (resPath)) return resPath; resPath = buildNormalizedPath (std.file.thisExePath.dirName, "..", "data", fname); if (std.file.exists (resPath)) return resPath; // Uh, let's just give up return buildPath ("/usr", "share", "appstream", fname); } /** * Check if a path exists and is a directory. */ bool existsAndIsDir (string path) @safe { if (std.file.exists (path)) if (std.file.isDir (path)) return true; return false; } /** * Convert a string array into a byte array. */ ubyte[] stringArrayToByteArray (string[] strArray) pure @trusted { auto res = appender!(ubyte[]); res.reserve (strArray.length * 2); // make a guess, we will likely need much more space foreach (ref s; strArray) { res ~= cast(ubyte[]) s; } return res.data; } /** * Check if string contains a remote URI. */ @safe bool isRemote (const string uri) { import std.regex; auto uriregex = ctRegex!(`^(https?|ftps?)://`); auto match = matchFirst (uri, uriregex); return (!match.empty); } private immutable(Nullable!SysTime) download (const string url, ref File dest, const uint retryCount = 5) @trusted in { assert (url.isRemote); } body { import core.time; import std.net.curl : CurlException, HTTP, FTP; Nullable!SysTime ret; size_t onReceiveCb (File f, ubyte[] data) { f.rawWrite (data); return data.length; } /* the curl library is stupid; you can't make an AutoProtocol to set timeouts */ logDebug ("Downloading %s", url); try { if (url.startsWith ("http")) { auto downloader = HTTP (url); downloader.connectTimeout = dur!"seconds" (30); downloader.dataTimeout = dur!"seconds" (30); downloader.onReceive = (data) => onReceiveCb (dest, data); downloader.perform(); if ("last-modified" in downloader.responseHeaders) { auto lastmodified = downloader.responseHeaders["last-modified"]; ret = parseRFC822DateTime(lastmodified); } } else { auto downloader = FTP (url); downloader.connectTimeout = dur!"seconds" (30); downloader.dataTimeout = dur!"seconds" (30); downloader.onReceive = (data) => onReceiveCb (dest, data); downloader.perform(); } logDebug ("Downloaded %s", url); } catch (CurlException e) { if (retryCount > 0) { logDebug ("Failed to download %s, will retry %d more %s", url, retryCount, retryCount > 1 ? "times" : "time"); download (url, dest, retryCount - 1); } else { throw e; } } return ret; } /** * Download or open `path` and return it as a string array. * * Params: * path = The path to access. * * Returns: The data if successful. */ string[] getFileContents (const string path, const uint retryCount = 5) @trusted { import core.stdc.stdlib : free; import core.sys.posix.stdio : fclose, open_memstream; char * ptr = null; scope (exit) free (ptr); size_t sz = 0; if (path.isRemote) { { auto f = open_memstream (&ptr, &sz); scope (exit) fclose (f); auto file = File.wrapFile (f); download (path, file, retryCount); } return to!string (ptr.fromStringz).splitLines; } else { if (!std.file.exists (path)) throw new Exception ("No such file '%s'", path); return std.file.readText (path).splitLines; } } /** * Download `url` to `dest`. * * Params: * url = The URL to download. * dest = The location for the downloaded file. * retryCount = Number of times to retry on timeout. */ void downloadFile (const string url, const string dest, const uint retryCount = 5) @trusted in { assert (url.isRemote); } out { assert (std.file.exists (dest)); } body { import std.file; if (dest.exists) { logDebug ("Already downloaded '%s' into '%s', won't redownload", url, dest); return; } mkdirRecurse (dest.dirName); auto f = File (dest, "wb"); scope (failure) remove (dest); auto time = download (url, f, retryCount); f.close (); if (!time.isNull) setTimes (dest, Clock.currTime, time); } /** * Get path of the directory with test samples. * The function will look for test data in the current * working directory. */ string getTestSamplesDir () @trusted { import std.path : getcwd; auto path = buildPath (getcwd (), "test", "samples"); if (std.file.exists (path)) return path; path = buildNormalizedPath (getcwd (), "..", "test", "samples"); return path; } /** * Return stock icon for this component, or null if it does not * have one. */ @system Nullable!Icon componentGetStockIcon (ref Component cpt) { Nullable!Icon res; auto iconsArr = cpt.getIcons (); for (uint i = 0; i < iconsArr.len; i++) { // cast array data to D AsIcon and keep a reference to the C struct auto icon = new Icon (cast (AsIcon*) iconsArr.index (i)); if (icon.getKind() == IconKind.STOCK) { res = icon; return res; } } return res; } unittest { writeln ("TEST: ", "GCID"); assert (buildCptGlobalID ("foobar.desktop", "DEADBEEF") == "f/fo/foobar.desktop/DEADBEEF"); assert (buildCptGlobalID ("org.gnome.yelp.desktop", "DEADBEEF") == "org/gnome/yelp.desktop/DEADBEEF"); assert (buildCptGlobalID ("noto-cjk.font", "DEADBEEF") == "n/no/noto-cjk.font/DEADBEEF"); assert (buildCptGlobalID ("io.sample.awesomeapp.sdk", "ABAD1DEA") == "io/sample/awesomeapp.sdk/ABAD1DEA"); assert (buildCptGlobalID ("io.sample.awesomeapp.sdk", null, true) == "io/sample/awesomeapp.sdk/"); assert (getCidFromGlobalID ("f/fo/foobar.desktop/DEADBEEF") == "foobar.desktop"); assert (getCidFromGlobalID ("org/gnome/yelp.desktop/DEADBEEF") == "org.gnome.yelp.desktop"); assert (ImageSize (80, 40).toString () == "80x40"); assert (ImageSize (1024, 420).toInt () == 1024); assert (ImageSize (1024, 800) > ImageSize (64, 32)); assert (ImageSize (48) < ImageSize (64)); assert (stringArrayToByteArray (["A", "b", "C", "ö", "8"]) == [65, 98, 67, 195, 182, 56]); assert (isRemote ("http://test.com")); assert (isRemote ("https://example.org")); assert (!isRemote ("/srv/mirror")); assert (!isRemote ("file:///srv/test")); } appstream-generator-0.6.8/src/asgen/zarchive.d000066400000000000000000000423141320016272000213460ustar00rootroot00000000000000/* * Copyright (C) 2016-2017 Matthias Klumpp * * Licensed under the GNU Lesser General Public License Version 3 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the license, or * (at your option) any later version. * * This software 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this software. If not, see . */ module asgen.zarchive; import std.stdio; import std.string; import std.regex; import std.conv : to; import std.path : buildNormalizedPath; import std.array : appender; import std.typecons : RefCounted, RefCountedAutoInitialize; import std.concurrency : Generator, yield; static import std.file; import asgen.logging; import asgen.utils : GENERIC_BUFFER_SIZE; import asgen.bindings.libarchive; private immutable DEFAULT_BLOCK_SIZE = 65536; enum ArchiveType { GZIP, XZ } private const(char)[] getArchiveErrorMessage (archive *ar) { return fromStringz (archive_error_string (ar)); } private string readArchiveData (archive *ar, string name = null) { archive_entry *ae; int ret; size_t size; char[GENERIC_BUFFER_SIZE] buff; auto data = appender!string; ret = archive_read_next_header (ar, &ae); if (ret == ARCHIVE_EOF) return data.data; if (ret != ARCHIVE_OK) { if (name is null) throw new Exception (format ("Unable to read header of compressed data: %s", getArchiveErrorMessage (ar))); else throw new Exception (format ("Unable to read header of compressed file '%s': %s", name, getArchiveErrorMessage (ar))); } while (true) { size = archive_read_data (ar, cast(void*) buff, GENERIC_BUFFER_SIZE); if (size < 0) { if (name is null) throw new Exception (format ("Failed to read compressed data: %s", getArchiveErrorMessage (ar))); else throw new Exception (format ("Failed to read data from '%s': %s", name, getArchiveErrorMessage (ar))); } if (size == 0) break; data ~= buff[0..size]; } return data.data; } string decompressFile (string fname) { int ret; archive *ar = archive_read_new (); scope(exit) archive_read_free (ar); archive_read_support_format_raw (ar); archive_read_support_format_empty (ar); archive_read_support_filter_all (ar); ret = archive_read_open_filename (ar, toStringz (fname), DEFAULT_BLOCK_SIZE); if (ret != ARCHIVE_OK) throw new Exception (format ("Unable to open compressed file '%s': %s", fname, getArchiveErrorMessage (ar))); return readArchiveData (ar, fname); } string decompressData (ubyte[] data) { int ret; archive *ar = archive_read_new (); scope(exit) archive_read_free (ar); archive_read_support_filter_all (ar); archive_read_support_format_empty (ar); archive_read_support_format_raw (ar); auto dSize = ubyte.sizeof * data.length; ret = archive_read_open_memory (ar, cast(void*) data, dSize); if (ret != ARCHIVE_OK) throw new Exception (format ("Unable to open compressed data: %s", getArchiveErrorMessage (ar))); return readArchiveData (ar); } struct ArchiveDecompressor { private: string archive_fname; const(ubyte)[] readEntry (archive *ar) { const void *buff = null; size_t size = 0UL; long offset = 0; auto res = appender!(ubyte[]); while (archive_read_data_block (ar, &buff, &size, &offset) == ARCHIVE_OK) { res ~= cast(ubyte[]) buff[0..size]; } return res.data; } void extractEntryTo (archive *ar, string fname) { const void *buff = null; size_t size = 0UL; long offset = 0; long output_offset = 0; auto f = File (fname, "w"); // open for writing while (archive_read_data_block (ar, &buff, &size, &offset) == ARCHIVE_OK) { if (offset > output_offset) { f.seek (offset - output_offset, SEEK_CUR); output_offset = offset; } while (size > 0) { auto bytes_to_write = size; if (bytes_to_write > DEFAULT_BLOCK_SIZE) bytes_to_write = DEFAULT_BLOCK_SIZE; f.rawWrite (buff[0..bytes_to_write]); output_offset += bytes_to_write; size -= bytes_to_write; } } } archive *openArchive () { archive *ar = archive_read_new (); archive_read_support_filter_all (ar); archive_read_support_format_all (ar); auto ret = archive_read_open_filename (ar, archive_fname.toStringz, DEFAULT_BLOCK_SIZE); if (ret != ARCHIVE_OK) throw new Exception (format ("Unable to open compressed file '%s': %s", archive_fname, getArchiveErrorMessage (ar))); return ar; } bool pathMatches (string path1, string path2) { import std.path; if (path1 == path2) return true; auto path1Abs = buildNormalizedPath ("/", path1); auto path2Abs = buildNormalizedPath ("/", path2); if (path1Abs == path2Abs) return true; return false; } public: struct ArchiveEntry { string fname; const(ubyte)[] data; } void open (string fname) { archive_fname = fname; } bool isOpen () { return archive_fname !is null; } bool extractFileTo (string fname, string fdest) { archive_entry *en; auto ar = openArchive (); scope(exit) archive_read_free (ar); while (archive_read_next_header (ar, &en) == ARCHIVE_OK) { auto pathname = fromStringz (archive_entry_pathname (en)); if (pathMatches (fname, to!string (pathname))) { this.extractEntryTo (ar, fdest); return true; } else { archive_read_data_skip (ar); } } return false; } void extractArchive (const string dest) in { assert (std.file.isDir (dest)); } body { import std.path; archive_entry *en; auto ar = openArchive (); scope(exit) archive_read_free (ar); while (archive_read_next_header (ar, &en) == ARCHIVE_OK) { auto pathname = buildPath (dest, archive_entry_pathname (en).fromStringz); /* at the moment we only handle directories and files */ if (archive_entry_filetype (en) == AE_IFDIR) { if (!std.file.exists (pathname)) std.file.mkdir (pathname); continue; } if (archive_entry_filetype (en) == AE_IFREG) { this.extractEntryTo (ar, pathname); } } } const(ubyte)[] readData (string fname) { import core.sys.posix.sys.stat; import std.path; archive_entry *en; auto ar = openArchive (); scope(exit) archive_read_free (ar); auto fnameAbs = absolutePath (fname, "/"); while (archive_read_next_header (ar, &en) == ARCHIVE_OK) { auto pathname = fromStringz (archive_entry_pathname (en)); if (pathMatches (fname, to!string (pathname))) { auto filetype = archive_entry_filetype (en); if (filetype == S_IFDIR) { /* we don't extract directories explicitly */ throw new Exception (format ("Path %s is a directory and can not be extracted.", fname)); } /* check if we are dealing with a symlink */ if (filetype == S_IFLNK) { string linkTarget = to!string (fromStringz (archive_entry_symlink (en))); if (linkTarget is null) throw new Exception (format ("Unable to read destination of symbolic link for %s.", fname)); if (!isAbsolute (linkTarget)) linkTarget = absolutePath (linkTarget, dirName (fnameAbs)); return this.readData (buildNormalizedPath (linkTarget)); } if (filetype != S_IFREG) { // we really don't want to extract special files from a tarball - usually, those shouldn't // be present anyway. // This should probably be an error, but return nothing for now. return null; } return this.readEntry (ar); } else { archive_read_data_skip (ar); } } throw new Exception (format ("File %s was not found in the archive.", fname)); } string[] extractFilesByRegex (Regex!char re, string destdir) { import std.path; archive_entry *en; auto matches = appender!(string[]); auto ar = openArchive (); scope(exit) archive_read_free (ar); while (archive_read_next_header (ar, &en) == ARCHIVE_OK) { auto pathname = fromStringz (archive_entry_pathname (en)); auto m = matchFirst (pathname, re); if (!m.empty) { auto fdest = buildPath (destdir, baseName (pathname)); this.extractEntryTo (ar, fdest); matches ~= fdest; } else { archive_read_data_skip (ar); } } return matches.data; } string[] readContents () { import std.conv : to; archive_entry *en; auto ar = openArchive (); scope (exit) archive_read_free (ar); auto contents = appender!(string[]); while (archive_read_next_header (ar, &en) == ARCHIVE_OK) { auto pathname = fromStringz (archive_entry_pathname (en)); // ignore directories if (pathname.endsWith ("/")) continue; auto path = buildNormalizedPath ("/", to!string (pathname)); contents ~= path; } return contents.data; } /** * Returns a generator to iterate over the contents of this tarball. */ auto read () { import core.sys.posix.sys.stat; import std.path; auto gen = new Generator!ArchiveEntry ( { archive_entry *en; auto ar = openArchive (); scope (exit) archive_read_free (ar); while (archive_read_next_header (ar, &en) == ARCHIVE_OK) { auto pathname = fromStringz (archive_entry_pathname (en)); // ignore directories if (pathname.endsWith ("/")) continue; auto path = std.path.buildNormalizedPath ("/", to!string (pathname)); ArchiveEntry aentry; aentry.fname = path; aentry.data = null; auto filetype = archive_entry_filetype (en); /* check if we are dealing with a symlink */ if (filetype == S_IFLNK) { auto linkTarget = to!string (fromStringz (archive_entry_symlink (en))); if (linkTarget is null) throw new Exception (format ("Unable to read destination of symbolic link for %s.", path)); // we cheat here and set the link target as data // TODO: Proper handling of symlinks, e.g. by adding a filetype property to ArchiveEntry. aentry.data = cast(ubyte[]) linkTarget; yield (aentry); continue; } if (filetype != S_IFREG) { yield (aentry); continue; } aentry.data = this.readEntry (ar); yield (aentry); } }); return gen; } } /** * Save data to a compressed file. * * Params: * data = The data to save. * fname = The filename the data should be saved to. * atype = The archive type (GZ or XZ). */ void compressAndSave (ubyte[] data, const string fname, ArchiveType atype) { import std.file : isFile, remove, rename; auto ar = archive_write_new (); scope (exit) archive_write_free (ar); archive_write_set_format_raw (ar); if (atype == ArchiveType.GZIP) { archive_write_add_filter_gzip (ar); archive_write_set_filter_option (ar, "gzip", "timestamp", null); } else { archive_write_add_filter_xz (ar); } // don't write to the new file directly, we create a temporary file and // rename it when we successfully saved the data. auto tmpFname = fname ~ ".new"; auto ret = archive_write_open_filename (ar, tmpFname.toStringz); if (ret != ARCHIVE_OK) throw new Exception (format ("Unable to open file '%s': %s", tmpFname, getArchiveErrorMessage (ar))); archive_entry *entry; entry = archive_entry_new (); scope (exit) archive_entry_free (entry); archive_entry_set_filetype (entry, AE_IFREG); archive_entry_set_size (entry, ubyte.sizeof * data.length); archive_write_header (ar, entry); archive_write_data (ar, cast(void*) data, ubyte.sizeof * data.length); archive_write_close (ar); // delete old file if it exists if (std.file.exists (fname)) fname.remove (); // rename temporary file to actual file std.file.rename (tmpFname, fname); // we need to use std.file explicitly, because otherwise core.stdc gets used } final class ArchiveCompressor { private: string archiveFname; archive *ar; bool closed; public: this (ArchiveType type) { ar = archive_write_new (); if (type == ArchiveType.GZIP) { archive_write_add_filter_gzip (ar); archive_write_set_filter_option (ar, "gzip", "timestamp", null); } else { archive_write_add_filter_xz (ar); } archive_write_set_format_pax_restricted (ar); closed = true; } ~this () { close (); archive_write_free (ar); } void open (string fname) { archiveFname = fname; auto ret = archive_write_open_filename (ar, fname.toStringz); if (ret != ARCHIVE_OK) throw new Exception (format ("Unable to open file '%s'", fname, getArchiveErrorMessage (ar))); closed = false; } bool isOpen () { return !closed; } void close () { if (closed) return; archive_write_close (ar); closed = true; } void addFile (string fname, string dest = null) in { if (!std.file.exists (fname)) { logError ("File %s does not exist!", fname); assert (0); } } body { import std.conv: octal; import std.path: baseName; import core.sys.posix.sys.stat; immutable BUFFER_SIZE = 8192; archive_entry *entry; stat_t st; ubyte[BUFFER_SIZE] buff; if (dest is null) dest = baseName (fname); lstat (fname.toStringz, &st); entry = archive_entry_new (); scope (exit) archive_entry_free (entry); archive_entry_set_pathname (entry, toStringz (dest)); archive_entry_set_size (entry, st.st_size); archive_entry_set_filetype (entry, S_IFREG); archive_entry_set_perm (entry, octal!755); archive_entry_set_mtime (entry, st.st_mtime, 0); synchronized { archive_write_header (ar, entry); auto f = File (fname, "r"); while (!f.eof) { auto data = f.rawRead (buff); archive_write_data (ar, cast(void*) data, ubyte.sizeof * data.length); } } } } version (unittest) { version (GNU) { extern(C) char *mkdtemp (char *) nothrow @nogc; } else { import core.sys.posix.stdlib : mkdtemp; } } unittest { writeln ("TEST: ", "Compressed empty file"); ubyte[] emptyGz = [ 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; assert (decompressData (emptyGz) == ""); writeln ("TEST: ", "Extracting a tarball"); import std.file : tempDir; import std.path : buildPath; import asgen.utils : getTestSamplesDir; auto archive = buildPath (getTestSamplesDir (), "test.tar.xz"); assert (std.file.exists (archive)); auto ar = new ArchiveDecompressor (); auto tmpdir = buildPath (tempDir, "asgenXXXXXX"); auto ctmpdir = new char[](tmpdir.length + 1); ctmpdir[0 .. tmpdir.length] = tmpdir[]; ctmpdir[$ - 1] = '\0'; tmpdir = to!string(mkdtemp (ctmpdir.ptr)); scope(exit) std.file.rmdirRecurse (tmpdir); ar.open (archive); ar.extractArchive (tmpdir); auto path = buildPath (tmpdir, "b", "a"); assert (std.file.exists (path)); assert (std.file.readText (path).chomp == "hello"); } appstream-generator-0.6.8/test/000077500000000000000000000000001320016272000164555ustar00rootroot00000000000000appstream-generator-0.6.8/test/ci/000077500000000000000000000000001320016272000170505ustar00rootroot00000000000000appstream-generator-0.6.8/test/ci/Dockerfile000066400000000000000000000026211320016272000210430ustar00rootroot00000000000000# # Docker file for AppStream Generator CI tests # FROM debian:buster # prepare RUN apt-get update -qq # install build essentials RUN apt-get install -yq git gcc gdc ldc # install dependencies used by both appstream and appstream-generator RUN apt-get install -yq --no-install-recommends \ meson \ gettext \ gobject-introspection \ gtk-doc-tools \ libgirepository1.0-dev \ libglib2.0-dev \ libstemmer-dev \ libxml2-dev \ libyaml-dev # install dependencies only for appstream-generator RUN apt-get install -yq --no-install-recommends \ gir-to-d \ libmustache-d-dev \ libcurl4-gnutls-dev \ liblmdb-dev \ libarchive-dev \ libgdk-pixbuf2.0-dev \ librsvg2-dev \ libfontconfig1-dev \ libpango1.0-dev # JavaScript stuff RUN apt-get install -yq --no-install-recommends \ nodejs nodejs-legacy RUN git clone --depth=1 https://github.com/npm/npm.git RUN cd npm && make install RUN rm -rf npm RUN npm install -g bower # build & install the current Git snapshot of AppStream RUN mkdir /build-tmp RUN cd /build-tmp && \ git clone --depth=20 https://github.com/ximion/appstream.git RUN mkdir /build-tmp/appstream/build RUN cd /build-tmp/appstream/build && \ meson --prefix=/usr -Dmaintainer=true -Dapt-support=true .. RUN cd /build-tmp/appstream/build && \ ninja && ninja install RUN rm -rf /build-tmp # finish RUN mkdir /build WORKDIR /build appstream-generator-0.6.8/test/ci/build_and_test.sh000077500000000000000000000005651320016272000223750ustar00rootroot00000000000000#!/bin/sh # # This script is supposed to run inside the AppStream Generator Docker container # on the CI system. # set -e export LANG=C.UTF-8 echo "D compiler: $DC" set -v $DC --version meson --version # # Build & Test # mkdir -p build && cd build meson -Ddownload-js=true .. ninja # Run tests ./asgen_test # Test install DESTDIR=/tmp/install-ninja ninja install cd .. appstream-generator-0.6.8/test/samples/000077500000000000000000000000001320016272000201215ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/Noto.LICENSE000066400000000000000000000100311320016272000220370ustar00rootroot00000000000000Copyright: 2010-2015, Google Corporation License: SIL-1.1 PREAMBLE . The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. . The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. . DEFINITIONS . "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. . "Reserved Font Name" refers to any names specified as such after the copyright statement(s). . "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). . "Modified Version" refers to any derivative made by adding to,deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. . "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. . PERMISSION & CONDITIONS . Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: . 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. . 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. . 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. . 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. . 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. . TERMINATION . This license becomes null and void if any of the above conditions are not met. . DISCLAIMER . THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. appstream-generator-0.6.8/test/samples/NotoSans-Regular.ttf000066400000000000000000011253201320016272000240070ustar00rootroot00000000000000GDEF4(GPOSGSUBF #p `OS/2SC`cmapO'hcvt 7fpgm6  . gasp#glyfL^dhead[x6hhea OT$hmtx=x%loca"8%maxp x namepostif prepf5\_< 4( b   o pRT`\K33f GOOG@X J 'D+3dmfRf=hTf%TR%db\+qZdf%%?fsfy1w3}s'}R/`1B?}?}dhsqN3N}^qqqqF{qqNh!J;%P 9h Bf'Byhy1dBRfRdm{f1#=q%LBPRGR.R y3 }ssss<R<=?}?}?}?}?}?} }^}^}^}^}^}^^qqqqqqqqqqqfq}^}^}^}q}q}q}qq=qsqsqsqsqsq}q}q}q}q,R3RR/`FF11\111?}q?}q?}qm}oNNbN~dhhdhhdhhdhhs!s!s!qJNPNPNP}^ ^?}qdhh+m#%31)sN?{RBqH?}JsohomBN<qXq % oXqqFV`oqFqqqhBsqBss1%}dhR</`}31 sN%%B?}}sohLT#=j-}^uw'qD%%;qq)o;%/?%9;y!qwqh;B}qJqJqJRRRJff?fT{T jdD{R{P y-m\D5/)o)/#BNfRER#RGRfb) Hfd%w `fffjo{=93Vy%TTf B{}^ zsF}q=dM1s%q%'f`wo= =omB}q!! }q}Fq{o'%{qhu))HF/=/y5D;^ND\uR/F% B;}#q}qs) j%)7R-7R-R{ LV R}^}^ ^sqyhyhNDH%%%%?}qB}qB}q=;=w9=/yf%;%q71o=HyNHLNV}#q?)mX}^}^}^}%}^}^}^}^}^}^}^}^sqsqsqsqsN?sqsqsqR{R?}q?}q?}q?}T?}q?}q?}qF}qF}qF}qF}qF}q=d=d=d=d=dqjjfqqqf-s!?}q={hqos{yo'}yFFV=B}}q{d`\Jy!!sBLVNPHqF9bHDJ!!!' V q`B!D%}^?}qh}^}^ ^}q}qF?}q?}qH V q}qJ}^}^sqsq1?}q?}qN#NNq^wqNP}^sq?}q?}q?}q?}q qq}q1shP}3sq/`#}qN}qD?bqqhhhXD3DqoqqJ B{{{qqBsoNNNNN%yyh-!=JPVPhh5hq?}\q=F{qhh5qqBq!!!L11'sfff5+5+PP!H3H3H'H++!!5+5+oBj+DXXXXXXXJhh%}}}})))V dfdf33LL-))) ~9Y}5Yj5}/}W~BW BF%T=TT'w=TTBBTTT )))DqD%?fo3}q}qqFsb+f={dsq5^d`31)T!}qs)3qqB}q;}B?}??}qqJ7hJ-yJV3+y-H33jhuyy7171+NLNN)VDd !5m?hqqodqy;TDbqmq'h%yZyh'bh}h}bXHfRhFhh\1X-;fbhh-;bhhqq{NF%V! q=oFR{NRhd;%P}^qqqXD1hDDhNZhHD/f'H!N!Nhbfb\1'D-RR^R-h}BBZT333}qqqqqqsqsqsqsqsq'}qZ>)FFF1111B{B{?}q?}q?}q?}qNNNNdhhdhhdhhdhhdhhs!s!s!s!qJqJ;%;%NPNPNP!J}^qqqqqqqqXXXXXX%VL##8qqqqqqBsBsBsBsBsBsBsBsqqXXDqqBsBsqqqqqqqq d X   w w BsBsBsBsBsBsBsBs {      w wqqqqqqq!?h,+hBsBsBsBsBs N!LRh N%')#yZ}hhL'}bJds{\'1}d}"d =R.R1-F y%dj#f{mmb))s+jVFR?;?;fBhf11}^!  7yNP#}%oDq!'''%f'' +VVVVVNVRVNVNVFFV5V5VPV-VH-V%V%V%V'V/%VVV5V5V/)VPVLVLVLV^LVVVVVPVLVFVLVLLV/V9V?V?V??V5V5V5V5V55VLVLVLVLVLhVLVFVLVLVLLVVVVVVVVVXVVVV\V7V7V7V7V77VHVFVFVFVFFVVV9V9V99VVVVVLVVVVVLVLVLVLVPPV/V5V5VV)V/V'V%V%V%%VHV-VPV5V5-VFVNVNVRVNFVVVVqqqqqqqq 3j3j3j3jd3^3^3j3j3^3^3^3^ysD- !;%#)u`f# \`` ~ac67"#ou~  OP\_'=?EMWY[]}  " & / 0 4 : < > D ^ p y  !!!!"!&!.!N!T!^!!!"""""""")"+"H"a"e###!%%% %%%%%$%,%4%<%l%%%%%%%%%%%%%%%&<&@&B&`&c&f&k&o),m,w.!# bd78#$tz PQ]`>@ HPY[]_  & * 0 2 9 < > D ^ j t  !!!!"!&!.!M!S![!!!"""""""")"+"H"`"d### %%% %%%%%$%,%4%<%P%%%%%%%%%%%%%%%&:&@&B&`&c&e&j&o),`,q. ^IvedAeY @SQzKIzx?wZI we%" {ob`aa` kLP>:6&$&8F0(.@@<"$ IJ$%KLM`abVPQWXYRh X Y Z [ \ ]STUV     ;<=>r i,-03PQ45Z[@G[ZYXUTSRQPONMLKJIHGFEDCBA@?>=<;:9876510/.-,('&%$#"! , `E% Fa#E#aH-, EhD-,E#F` a F`&#HH-,E#F#a ` &a a&#HH-,E#F`@a f`&#HH-,E#F#a@` &a@a&#HH-, <<-, E# D# ZQX# D#Y QX# MD#Y &QX# D#Y!!-, EhD ` EFvhE`D-, C#Ce -, C#C -,(#p(>(#p(E: -, E%EadPQXED!!Y-,I#D-, EC`D-,CCe -, i@a ,b`+ d#da\XaY-,E+)#D)z-,Ee,#DE+#D-,KRXED!!Y-,KQXED!!Y-,%# `#-,%# a#-,%-,CRX!!!!!F#F`F# F`ab# # pE` PXaFY`h:Y-, E%FRKQ[X%F ha%%?#!8!Y-, E%FPX%F ha%%?#!8!Y-,CC -, %EPX ED!!EDY-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,KSX%Id#Ei@ab aj#D#!# 9/Y-,KSX %Idi &%Id#ab aj#D&#D#D& 9# 9//Y-,E#E`#E`#E`#vhb -,H+-, ETX@D E@aD!!Y-,E0/E#Ea``iD-,KQX/#p#B!!Y-,KQX %EiSXD!!Y!!Y-,EC`c`iD-,/ED-,E# E`D-,E#E`D-,K#QX34 34YDD-,CX&EXdf`d `f X!@YaY#XeY)#D#)!!!!!Y-,CTXKS#KQZX8!!Y!!!!Y-,CX%Ed `f X!@Ya#XeY)#D%% XY%% F%#B<%%%% F%`#B< XY%%)) EeD%%)%% XY%%CH%%%%`CH!Y!!!!!!!-,% F%#B%%EH!!!!-,% %%CH!!!-,E# E P X#e#Y#h @PX!@Y#XeY`D-,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,!KTX8!!Y-,CTXF+!!!!Y-,CTXG+!!!Y-, T#T[XCPCT[X!!!!H+YCPCT[XH+!!!!YY-, T#T[XCPCT[X!!!I+YCPCT[XI+!!!YY-, #KSKQZX#8!!Y-,%%Ij SX@`8!!Y-,%%Ij QX@a8!!Y-, #Id#SX<!Y-,KRX}zY-,KKTB-,B#Q@SZXB TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY&QX@cTX@C`BY@cTXC`BYYYYYYCTXBY-,Eh#KQX# E d@PX|Yh`YD-,%%#>#> #eB #B#?#? #eB#B-,CPCT[X!# Y-,Y+-,-@ !3 U     U3U?[PZU?ZOZZXUYPXU0X@XPXXWPVU VVVTUUPTUpTT0T@TTTT0MMNUGdFU?FFFKUJPIUIKUOPNU3NNKULPKUKK?KKSPRU;RRPUQPPU7$~adX}wsvsAus2ts2sss3U3Umili&ki=jiHiZ&&H&H&&&###3@mUU3U?d]4xcb]#a]3`]*_]*^]3]]]]dU3U3UOUdUoTS++KRK P[%S@QZUZ[XYBK2SX`YKdSX@YKSXBYss++^stu+++st+++++s+st+++ssttt+++++++stu++++s+s++s+st++s++++s++sstt++st+s++s+st++ssst+^ PuHjJ3  ` @5 }jHHHHnP8z0  v  "  <`pB:N*|(bX H(n* !!"d"#$$$%%%&b&'X(())*B*++,,,--./ / /|0*012x234D5B56h6678,899:B:;;r;<">??>?n?@xA6A\AAABBLBzBBCCD D8DhDDE<F"FRFFFGGHtHHHI I2IZJJJJKK@KhKKKLLMM<MbMMNLO OFOjOOOPPPQQ@QfQQQRR4RXRRRRS.STSdTXTTTUU4UZUUUUV(VLVzVVVWW>WnWXVY"YPYvYYZZ(ZNZrZZZ[[L[|[[\>\l\\\]]6]\]^^h^^^__6_Z_```aa8a^aabcccddDdtdddee@eheeeff,fZf~ggghhFhjhhhi iRixiiijjJjnjjjk"kJkxkklmoo>odoooppbppq^qr*rrsrstXttttu$uPuuuuuv6vFvVvfvvwBwRwbwwwxVxfxxy>yNy^z@zPz{{||(|L|p||}~^~nbl|NxrN"Fl<j 0brJ JZ Htb6HX 6\(~HX*Z@r$:<L*h4Z <d*RF R| D"r N|NN ĂlvT|ǢPȔ*ɬPʖnnnnnnnnnnnnnn2 "КhіѼ "ҢVӔԊRְ֞<vצ"ټچX2ނN4. *p(NZ\$tlP"B2Z*lBh"  " H       " *.TdVlTP` 0`2Bv * R !!!" "F"x""""##L#v##$$*$\$$$%2%%%&&'h(()n))*+,v-:-./V/01r223>3445H56 646h6667(7R77899F9|99::<:v:;<<>>4>j>??@>@r@@@A AHApAABB*B`BBBD4D\DDEE&EVE|EEFF(FPFxFFFG(GVGzGGHH*HXH|HHHIILIrIIIJRJKTLLMbMNOfOPP&PNQ>R>RNSST8TUtVV$VWfXXYlY|ZNZ[\l]]t^^_F_`aDaaabcd2eefVfgghrhiijk,kl@lmn.nojp>qqr2rszsstftvttu&uLutuuuvv@vfvvvww>wbwwxx,xlxxyyyz zHzrzz{||}}F}v}}~ ~@~p~~~ 8\ ,V 8^Fp"Rx*:*Xn F| 8`xH2 |lv(86dH,~NBRbj@Ph\l t(FT\lX&D<.j```8@(ÆÜĊŤfv>Ǹn0̀rVИьJӚԶrnR׬:Pf,Br۠ 2b܈ܚܬ&8J\n݀ݢެh<rBx*Zj*hT0Z,>P*f8f0pHTzBTfxFx0Vz@h L p$^pl8L~P$^|R|>lFB*P^p 6hxV 2  n 6   b2r tF:d"2BRbrj*:l&6Fvd < !!">"#0#$$%%&&'(()H)*Z*+6+,--.,.//0R01&1p112\23<345V56*67778@889d9:.:;N;>?P@X@AzBBC`DDE.EFBFG2GGH HI*IJJJKzL$LM>MNNOFObO~OOPFPdPQnRSTVW XHY0ZZ[\]^4_`2`a*b$bcdefPgXhhriVjjkl`mmnPnopqr|stzujv vwHwxyDyz{`{p{|b|r|}}~:~<v,PBLH z(z@P P4L|*b*Rz8t`> N,T<z<fJfJx Fl>zJ&Tz*Rx4jBj>l V J FLp6\ :b6lBp0V~@h(\ 2X~ P Fl.TP"Hp:j6j 2Z,`$Lt8h 2X"JxDx>d Fj:t X JÐdĴ:pŦLƂƸ<ǂTȢ(dɠVʔXˠ0v@f͞ XΆξBϰ(8"X~Ѳ :jҚrԨHn՘.^b:`؊ش(RـٸHۈ6pܖ.^݊ݲlގ `ߊߤ,V&&>NBz\b:X 8XB6Jp:^BL\lzH8p(hDPz:b P  H  ,     L t<j&(!""Z"""#*#Z##$6&&','(:)d*N+`,&--.z./2/0X1<123B446667889 9:<:;^< <=B=>V>??~?@ @P@@ATAAB(BZBCCBCpDDDEEJEFFpFGG^GGHFHHI(IxIJJlJJKFKKL@LLM"MxMN$NfNNODOOP<P~PQQrQR R`RRSDSST.TTUUfUV V`VVW<WWX.XXYYVYYZPZZ[2[[\$\r\]]l]]^F^^_F__``h`aabaab@bbc6c~cddddeeLeef>ffg,ggh hbhhiPiij8jjk(k|kllVllmLmmn.n~noofoopHppqqDqpqqqr rLrvrrrssHsrssst tLtxtttu(uTuuuvv6vdvwxLyyzn{{|4|}:~~*vBHf:JV.,:&  "8Nd @  /2/3993310!!7!!IhyJh9@  P`  }Y ??+9/_^]]993310#34632#"&Nu3A>>AC<=BBGI@@LJ@  ?32993310#!#H)q)9(q)3{@C    !?O   ?3?39/333339/]33333933333333333310!!#!#!5!!5!3!3!!!?TTPNA+RR'RR%@}TTHNNH &-s@? '% *!!./$**%  vY +vY@//]]33+3/_^]33+393339333333310#5.'5.546753&'4&'6˼rDKcͪʭ8J^sVj^b##3AG= Z6`{dHU( IZ&uZdB  ,0G@% '!-'/12* * * $0/$?3?3??99//33933331032#"#"&546323265#"#"&54632 #GNNGɝGNQMNGɞ՝+LJڧH"Jm 3^@5%"+&,)&. 45%.+1& ((- lY1 iY1?+?+?9/9999993333310>54&#"27%467.54632673#'#"&GP|ffQYiVaMA$Ƴ]3E+rAOE~QL\^S\qhWek;m\lݬfZH?9310#H)q)R) @   $??99331073#&R1 ή26= @  $??993310#654'31:1T{E@*      ?  /?]9/]39933310% '%7)󰮞+wo`f`Dof) 4@  /_/]333933310!!#!5!3hhZT@/?/]9910%#67{7yA%RBu(@/_/]]]399105!Rՠ @  }Y ?+991074632#"&A<=DD=;BoBGGBAKJ??9910 #!Jd/ (@  sY sY?+?+993310#"3232#"/ꑞr~r!74" $@    ??9/9993310!#47'3װ fy^tUcy3b)4@ sYuY?+9?+933310)5>54&#"'632!)9p7xZe`FQt32򝒯t[]crg}akZZ`"-.2!iv5F{GQ+j @@   uY ??9/33+3993333310##!533!47#jԯD} 7JLL0̉h=@sYuY sY?+?+9/+993333102!"'53265!"'!!63JcvZ7#sO,4(9Xq3$R@, !!%&  vY  _  vYsY?+?+9/_^]+999333310!2&#"3632#"&2654&#"qtALe nזzWWPqZ̬%ڲHDddZ/'@uY?+9?9310!!5!Xd-"/L@'-&&- -01 ** #vY vY ?+?+93999333333102#"$54%.54632654&'">54&H/xn2v6fps˺nKVz̽Nqtw`C>]pc?`L/9Ydof)%P@+"  &' vYPsYvY?+?+9/_^]+999333310!"'532>7##"&5432"32>54.)`tDMgo pՖyZTOFЪ &I|Edef (@ }Y }Y ?+?+99331074632#"&4632#"&A<=DD=;B?>?BD=;BoBGGBAKJBIHC@KJ?f/@   }Y ?+/_^]910%#674632#"&h4|A ?>D=;Bh2\BIBIJf+(@0p/_/]3/]/]10%5 +;fs6@  O//]3]]]29933105!5!sVThf+*@0p/_/]3/]/]10 5f;BnfXD'D@&"()P` %%}Y% ~Y?+?+9/_^]]933105467>54&#"'632432#"&L`mDxP_?վ(QycA:CD98G7wP\PP5cj(.eJrfeUo["ӉEDCIBwJ6@K@%*$/7<</AB3>399 , 3',%?3?39/3339/39933333310#"&'##"&54>3232654$#"!27# $!232&#"YiUt 'dkȀECYn>/lQ INیcOS_˲u,ҭXTd߶5 ,@   iY ?3?9/+99210!!#3 '\;:ZF!;DhxcE!b@5 "#kY:kYkY?+?+9/_^]_]]+9933333310! #!!2654&+!2654&#&' Hnxj}}&@ iY iY ?+?+9310"327# 4$32&9]p?J):"hTVPZ(@   kYkY?+?+993310)! !#3 ZuiU|R U@1   iY: iY iY?+?+9/_^]^]]]+933310)!!!!!1Ty8 F@+  iYI?_o iY?+?9/_^]]+93310!#!!!!1R};=@ iY iY iY?+?+9/+933310!# 4$32&# !27!BtWF 3%&cVVT#% E@'  iY8i0 ?3?39/]q]]q+99333310!#!#3!3%VjRb 9@   nY nY?+3?+393333310)57'5!bj')jj)n'`{u @  iY"?+?93210"'532653^:GMdd{yra 8@     ?3?393993333310!##373~ /F@iY?+?9931033!Ǹ{0@   ?33?3999333310!##!3!#47#LRJN,@ ?3?39999333310!###33&53N - QGs'B9} (@  iY iY?+?+993310! ! 32#"_G>b|nheq,&%)o 2@  kYkY?+?9/+9933310!##! 32654&+o꨸%Ķ!}@@!    iY iY?+3?+_^]933310! ! 32#"^3_G>b|FJheq,&%)A@    kY   iY ?+?39/+399333331032654&+#! #۲ѸEeq\h%:@  &' iY iY?+?+999333310# '532654.'.54$32&#"]`<ˮ۸99LE(.~nI^R4JɟRNpeH_N232%26=T#R|lwWD7S` igINA}w4 ,2}cjrV\{!<@  "#  ]Y]Y?+?+??9999333102#"&'##336"32654&o7 oǦ\POxqqq^(@  aYaY?+?+993310"32&#"327f P37br#+!4@;q= @@!  !" ]Y]Y?+?+??999333310"323.53#'#'26=4&#"3w  sƤ( .y쓧!q^K@(    ^Y]YaY?+?+9/_^]_]+99333310"32!3267"!.Xj[/+9m-' ߦ;@  ]Y ^Y?3+3?+?9333310!##5754632&#"!il0]F[XBT>?%xGq=^ (I@&" (()*]Y]Y %]Y ?+?+?+?9993333310%26=4&#"7##"32373#"'53265Poy +u) 2FVL4@     ]Y?+?3?999333310!4&#"#33>32w 1q8Z@PZ5s)@  cY???]]+9310!#34632#"&b=-*??*-=J)<66<;88s 6@ cY`  ]Y?+?_^]]+93210"'5326534632#"&-^@ECNI%=-*??*-=UW_<66<;8838@     ?3??939333310?3 ##3`=F_D}5NTs+mmӲb@ ??9310!#3b^"B@!"#$  ]Y?3+3?33?999333310!#"#4&#"#33>3 3>32#ߙmt /jN 5tÂJPZX`5L^2@      ]Y?+?3?99933310!4&#"#33>32w 3oJQY5qh^ (@  ]Y ]Y?+?+993310#"&53232654&# h| ã'ҋ +{^!@@! "#  ]Y]Y?+?+??999933310"'##33>32"32654&w @n)N==6ZP۸#q=^ >@  ! ]Y ]Y ?+?+??999933310%26754&#""32373#47#Rou s%Օ,  /n</^,@   bY?+??99933102&#"#33>I8=:WT?^ `gJmphy^#:@  $% ^Y^Y?+?+999333310#"'532654&'.54632&#"yـ|w~;=ptd>/EXXJAZ:73`E D_Jy` !'3J"@  !  ?3?3399910!&'##3376733673/2* Ӻhm Ľ  @jMbJkZW>Zk#OMILJ%J .@      ?3?399933310 3 3 # #1bJJ,@  ]Y?+?3?999331033>73#"'5326?K @'EKJ2FVx&9J_%=o _cPsJ 8@ dYdY?+9?+993310)5!5!!sNTwG9^@8  x//$?3?39/]q]]]]]39933333310>5463.54 v׿tpslvn΁y]`/^_' |jdX-hY@ ??93103#閖B\@7  x//$?3?39/]q]]]]]39933333310#565475&54&'53zvmπzVgϚ)' '+dYiXfL+X*@@H ?o/]33+229910"56323267#"&'.P56dFwQI^.66fH~HI^C6l"@9n! ^8@ _o   }Y ?+/9/_^]]9933103##"&54632w3A>>AD;;DHCFEDBIHU@"  tY tY p  @ H    ??99//+]3+3+93333310%#5&5%53&#"3267qv5eY?9>55#BHZ@0   wY sYuY?+?+9/_^]3+39933333102&#"!!!!56=#5346@uz_AKTNy`-/׈/y'[@1   ""() P%/]3]29933333333333331047'76327'#"''7&732654&#"HddyhcHH`gzbbHooonulaGGaotc`EG`lwoprsq@C     wYo wY  ??39/]3+3/_^]]q3+3933333310 33!!!#!5!5!533Hnd5˰6i(@ ??9/9/9333103#3#閖y.:U@- 5/"/)55);<8,383 lY  &mY ?+?+93393333333310467.54632.#"#"'532654&'.7654&'VLJR\k7aJsmt҈WMjŏ6yAR)W$(pT{*';=8T7Cl\PC'-JG=O=I3KF>LoQm:c1 q 0@   0  /]q]3339933104632#"&%4632#"&18('::'(88&'::'&8s5//552255//5522dD&6L@.'// 78p    #3+#?3?39/]39/]3933310"327#"&54632&4$32#"$732$54$#"}wu_x}6^ZƬ֭+*Bw!=@  "# @?3]29/399333310'#"&546?54&#"&'632%32=^aqsNDdjzNnbobVcdggj-=<5>&b/9Rs 3@     0/]q3/39333310 % RX])JKJKf)*@/_/]33/99310#!5)RBudD&6i@= ' //78p#3+#?3?399//]3]39/q3933333331032654&+###!24$32#"$732$54$#"fQYRZdVJ^^m+*լ֭PAIASysb^ZƬ֭+*.@+;k{/_]]q33310!5! {V @  ?329933104632#"&732654&#"{{sOQnnQPrOqrNPqpf) D@(     /_/]q333/393333310!!#!5!35!hh!Z71Ju,@   ?39?399333310!57>54&#"'632!sGK>>d5H4SJn{qEAB0(^qo.OQ\#9!K@+  "# _ !?3?39/]]qq399333310#"'53254+532654&#"'>32wtuug_MBh{JJQ9,:FqNA;BN^7.y! "@  o  _  /]]]9910>73#&u(,?w0N@1NJ9@     ]Y ?+???39999333331032653#'##"'##3b mݒZ <\J6qd'@ ?3/39/93310####"&563!dvw>T1Z3H^ @  }Y /+99104632#"&A<>CD=;BAJK@@KJ1@   @ H/?39/+399333310#"'532654'73A%$HKMXw5cl p '3Ym&LJ @   ?2?9/9933103#47'V.G5Cs&]dB '@ @ ?3]2993310#"&5463232654&#"íXfdZZddZmywwyyttPs 3@     0  /]q3/39333310 ' 7' 7]hZeK_^JdeK_^JdG'&{;) ?55.'L&{t^?5 -'';su ?553w`^%W@7  &'_o ##}Y# ~YO_O/]q+?+9/_^]]93310327#"&54>7>=#"&54632ZJdFw?(Rxg=>?I46I5uTonT`mXbIqfgZoX!/GBIBBs&$CR@ %&+5+5s&$vR@ N%&+5+5s&$K'R@ %&+5+53&$R R@ #%&+5+5)&$j9R@  %#&+55+55$V@-    %&  o "iY " ?3?9/+_^]23399333333210#!#.54632'4&#"326m<3554&# #4632-OA@udŸn@DQpviDHJAp>I"(BL\dE(.GhGK}W?i57\3NVT^!&DC*&%+5^!&Dv1 +/*%+5^!&DK3-%+5^&DR/;%+5^&Dj&8%+55^&DP,&%+55^^(3:y@A )/88/;<#& 0`Y77dY7777& 4 ^Y !aY!&&,^Y&?+3+?3+39/_^]_]++99933333310%754&#"'>32>32!!267# '#"&7326="!4&^qt8Gg+6pB5X^Xf}RƈhVw }1NEzvT(6S]U]o!+' |k\Vcj*q^&FzL 1 %+5q!&HC!% %+5q!&HvP [%! %+5q!&HK )# %+5q&Hj . %+55p!&CQ %+5C!&v$ m %+5c!&K  %+5*&j %+55qh'l@< ""()     ^Y %]Y?+?339/+9/9_^]99333333310#"54327&''7&'774&#"326h^ ;MVbIfN˗3wֱp:3{IKnuu菦L&QR  * %+5qh!&RC!%+5qh!&RvZ >!%+5qh!&RK %%+5qh&RR !-%+5qh&Rj*%+55f+ Q@7  0 @ p  ?/_/]33/]32/]q3933105!432#"&432#"&fspB.0CspB.0C{{B;;{{B;;qh"T@/  #$  ]Y  ]Y?+?+99933333310#"''7&327&# 4'326hqRv\ uPy]1Il/=El'CsP +JsN`r4`d/D!&XC %+5D!&Xvu S %+5D!&XK" %+5D&Xj!' %+55!&\v ]! %+5{!A@" "# ]Y ]Y ?+?+??999933310>32#"'##3%"3 4&dCjx >%[Mҟ(56FN'&\j* %+55&$MBR@%&+]5+5^j&DM)(%+5>&$N/R@ %&+5+5^&DN)1%+5=&$Q%+5^=\&DQ 23%+5}s&&vR@ !&!%+5+5q!&FvH   %+5}s&&KR@ %&v%%+5+5q!&FK I$ %+5}7&&OR@ !&u%+5+5q&FON U %+5}s&&LR@ "&v$%+5+5q!&FL Q# %+5Zs&'LXR&%+5+5q&G8 \!!%+5=Zq(|@H&& )*_Y#]Y  ]Y?+?_^]+??9/_^]^]3+399933333310"323.=!5!533##'#'26=4&#"3w  Ls£& *n(})#&(MR@& %+5+]5qj&HM  %+5>&(N R@  &  %+5+5q&HN ' %+5&(Of5@ &  %+5+5q&HOR " %+5=&(Qm %+5qZ^&HQb&!%+5s&(L R@ &  %+5+5q!&HL (# %+5};s&*KR@ )&z)#%+5+5q=!&JK 60%+5};>&*NR@ &y'%+5+5q=&JN ,4%+5};7&*OXR@ %&"%+5+5q=&JOZ  )/%+5};;&*9% ;%!%+5q=!&J: -.2%+5%s&+KR& %+5+5L&KK!@ $&$ %+5+5m@<   lY` iY0 ?3?39/]q+9/_^]33+3393333333321053!533##!##55!ǸǸmV/Ls@A      _Y    ]Y   ?3?9/]]+9/_^]^]3+399933333310!4&#"##5353!!3>32wN 5lՇX@UU^3&,RR@  &! %+5+5&R  %+5,&,MR@& %+5+]5<j&M %+5>&,NR@  & %+5+5G&N %+5R=b&,Q  %+53=&LQ  %+5Rb7&,OPR@ &  %+5+5bJ@ ??9310!#3bJR{+&,- % %+5&LM +%+55`{us&-KR@  %&+5+5]!&7K@  %&+5+5;&.9%+5;3&N91 %+53J5@   ?3?39393333103 ##379a TJoJ㋉fs&/vnR@  %&+5+5A&Ov"@ k % &+5+5;&/93ô %+5\;b&O9 %+5&/8%@   %+5?5&O8; %+5&/Oi S %+5&OOL8 %+5 H@(     @ iY?+?9/_^]993333103'73%!eGI9zgX># 3@     ??9/9933323107#'73TLϴiIf[yDHBys"Ns&1vR@ &N %+5+5L!&Qv} Q %+5;N&19 %+5;L^&Q9Xʹ %+5Ns&1LR@ &  %+5+5L!&QL# ! %+5'Qv %+5{N;@  iY"?+?3?3999333310"'53267##33&53b:GUfm {unmVN^<@ ]Y]Y?+?+??9933310"'53254&#"#33>32'V;<>w} 4nȏkJRX}&2MR@&%+5+]5qhj&RM%+5}>&2NR&#%+5+5qh&RN #%+5}s&2SR@ +&G!'%+55+55qh!&RS\ >!'%+55}n@@  !iY:  iY iY  iY iY?+?+?+?+9/_^]^]]]+9333310)# !2!!!!!"327&f`YAjZ%L5uVUig8#\!o'\*1m@;%//%23 .^Y.... +( (]Y aY"]Y?3++?3+39/_^]_]+99933333310 '#"32>32!!26732654&#"%"!4&ހ?ш><~'DZh],={ qr4 +romtm-(;՟s&5v{R& %+5+5/!&Uv D %+5;&59 %+5b;/^&U9  %+5s&5LR &" %+5+5~2!&ULz %+5hs&6vNR@ q/+%/&+5+5hy!&Vv [-)%+5hs&6KR@ 3-%3&+5+5hy!&VK 1+%+5h&6z+ܴ,&%+5hy^&VzԴ*$%+5hs&6LR@ 2-%0&+5+5hy!&VL 0+%+5;\&79 %+5!;F&W9  %+5\s&7LR@ &%+5+5!&W8s  %+5\G@&   kY  iY?+3?9/_^]3+3933310!5!!!!#!59H70и1ᤤf!Fd@5   _Y `    dY]Y?+?+333/9/_^]3+39333333310%27# 5#535#5?3!!!!!U@k9ċHk=+U ^VHjk3&8RsR@ &'%+5+5D&XR * %+5&8MR@&%+5+]5Dj&XM  %+5>&8NR&%+5+5D&XN  %+5&8PR @ H&%+55++55D&XP'  %+55s&8SR@ %&H!%+55+55D!&XSq L$ %+55=&8Q# %+5=iJ&XQ!" %+5Vs&:KVR&&& %+5+53!&ZK -' %+5s&<KR@ &%+5+5!&\K % %+5)&<jR@ & %+55+55NDs&=vBR@ I%&+5+5Ps!&]v U%+5ND7&=O=R@ %&+5+5Ps&]O %+5NDs&=LR@ %&+5+5Ps!&]L%+5 !@  ]Y?+?93310"#!2&^Wkdh/Zuvb'D@$   ! dY ]Y]Y?+?+9/3+3933310"'53265#5754632&#"!!JICF;\Lע]u-f9^N`sT>+!dy>".y@G0 ) ## /0!@ H!!&` ,iY ,@,P,, @ H ?3/+]9]39/+9/_^]39/+9333332310#!#&54632&'>73#4&#"326q6-dxgg/(9_?y@31A;73@A^!w6bwx6=kh\C'**7;;76=;^%1=G@W&28,## ,2>CIHBBB@ HB@>P>>5;//////)) ) ) `Y ^Y^Y?+?+?9/+9_^]]q32]+]933333310!'##"&5%754&#"'>32%26=#"&546324&#"3265>7!T#R|lwWD7S` i}fgyxhe~qA12A;83?.j gINA}w4 ,2}cjrV\7evvcavva6==66==]*x iDs&vTR&]%+5+5^!&v lD@%+5}s&vR@ -&L-) %+5+5qh!&vX <,( %+5h;&69Ӵ/+%+5h;y^&V9޴-)%+5! *@  o  _  /]]33/]99910>73#&'#}g4ZX{+e58! *@   o  _  /]]3/]2999103673#&'{ri~a3<!Js~?`f+j @/_/]29910!!+`j ,@  /_/]]22/]39910"&'332673X nTsebq يG;?Cs $@   0  /]q]399104632#"&=-*??*-=s<66<;88m/ 0@     _/]]3q/2993310#"&546324&#"326/}fgxxge~qA12A;83?evudbuva6==66==#=u @   //]3993310327#"54731+,7E:ӠFF.. swBm0@   `/]]r22]229910".#"#>3232673+ROI"12h ta-UNH 01g t%+%;73#%>73##h'!Bgi/j!Bf.P87A887q @    _  /]]9910>73#5 i8lKI?X =@"     0/]q]3339/93310673#'432#"&%432#"&8$q=V_&88&)6^%92,*4;Kd/55225d/5-:2&$T%+5?5H^yu&(}T%+5?5'+T%+5?5P',T%+5?5&2DT@ =%+5?5'< T ޴%+5?58&vBT@ #9%% %+5?5&U@ #)%+555$%@iY?+?99310!#)}((ND=%+{Z@7  iYJzIo  iY iY?+?+9/_^]q]]qq+93310!!%! ! 32#"k_G=ez7Enies-%%'Rb,. @    ?3?99210 #&'#I"R Jυcd{0N1H' L@.   iY:  iY iY ?+?+9/_^]^]]]+910!!!!!5Rs!L }2%@ iY?+?3993310!#!#!%Io3J^ A@"    iY iY?+3?+39993331035 5!!' %!J-f`Nd!\7<h"+e@7' +,-"$$kY* *kYP`??9/]+339/_^]3+39333333310332+#5#"$54>;32654&+";۶D'+A˶87˴M׽Ѳ;mD@#    kYo??339/]+3393333310!##"$&53!333 3+-/!\y|NE@$    !iY  iY?3+399?+933333310"!5!&5! !!5654!ld:>bk+tX4^sG<|)&,j R@ !&  %+55+55)&<jR@ & %+55+55qq&~T 561%+5Xq&T `/+%+5Lq&T? H %+5q&T%+5y&U;@ .%+555q^ ,C@"# ))-.* ]Y ]Y& ?3+3?+?999333310%26=4&# "323673327#"&'#Rۍ{y6 )1# A"WZ< XЕ* +TT\8EfV?4 VQWP(T@,&& &!)*!""!]Y"" ]Y ]Y ?+?+?9/+99333333102#"&'#46 3 4&+532654&ȻoJGhPmXз3ǻ!$4%/-y J!@ ??393910#4733>73!<-C%A Aٻj-7["{>]0(MHuof*E@# %+," ]Y(]Y?+?+99993333310.54632.#"#"$544&'326sǩhNeWR`mլ]wªOb.@80LAEk[uҳw|I-֡X^%e@9## &'%%]YE%%%%%%% !]Y ]Y ?+?+9/_^]^]]]+993333310# 3267#"&54675.54632.#"!וʔUdqcjoWDcJ9Y]'/Kc& ]%),qq$6@  %&" ]Y?+3/.39933333310#654.'.54>7#5!1nY.Ty9T;{Re(-&#g`vG"qL^3@      ]Y?+???999333104&#"#33>32v 3oJQYIqR g@@]YIYiX  ]Y  ]Y?+?+9/_^]]]q]]]+99333310#"322!"! R  s nzl((  J@ ]Y ?+?993103267#"&5ZJT,bp6Jcb 3JV!"1@#$  ]Y ]Y?+?+?93993210#'.#"5632327#"&'&'# 7"1C1>5DC^|[8b/$%2CJZ U!P5YB! <%96 J[S~NJw J@  ??2992103363# #"J%ac[Moq0d@3(+ % %++12_Y ".( ]Y ?+/.39/_^]+993333333333104675&5467+5!#";#"#>54&'.oٌg>6}2\R{7Bw* >s/ N]piNa;#!nYJ26;"qh^RJ7@     ]Y]Y?+?+33?93310%27#"!##57!#5%1V/ߓXLNHJf^3@   ]Y]Y?+?+?99333310#"'##32%"32654&fy t%\D  Йdqq^.@   ! aY?+/.399333310#>54.'.532&#"+9{4G/qZR99lN"o\E4&-((9"4qJ 5@    ]Y ]Y?+?+399333310#"5)!3265'#"f{Tť?!>J,@]Y ^Y ?+?+39310!327#"&5!57ThF'q0ٖJuPHyJ)@   ]Y?+?39933310"&3!2654&'3u-%' Xћ|q\^"F@$   #$]Y  ]Y?3+3?+??933333310$746324&#">ыYO^܈sxeGO!*`u{#b &)rr\P 7@!"^Y ]Y?+??+999321023327#"&'#.#"56:P?-:R)QB,0A>s<ӨE4(5P-YtTkQv}lHR\ A@! ]Y ?3+3??3?933333310>54&'3#$3h$@dsȃ&  !ysJ'C@!  ()& ]Y#?2+3?39/993333310"4733265332654'3#"'#;>B;uj_fe]hz;BB7зE A( Ԏ|6ʀǝٸ&j  "%+55y&j7'%+55qhq&RT# !3 32654&+/8USmE@4=:Q8GHy!NbWul!z\b@7   iY :     kY?+??39/_^]^]]]3+3933333310)!#3!33 32654&+\sw!PbVj!zT>@    iY iY?+3?39/+9333310!2#4&#!#!5!!۸w {l#s&vR@ &%+5+5b&6FR@ &" %+5+5 0@  "iY?3+??3933310)#!3!34@۶$ W@1  iY :    iY kY?+?+9/_^]^]]]+99333310)!!3 32654&+TdTἩ8t%a Z ?@  " jY  iY?+33?+?39333310#!#36!3!!Zq%Hlh(=@!    ?33?33993333310 333 ###N//Jű<<<NF']@3#  ()kY: %%kY% kY ?+?+9/_^]_]+993333310! '532654&+532654&#"'6!2'cbןrmX`O/1{j{6G}`(@    ?3?2999933310333#47##ɬ  $ͬ U*Jh)?`b&6R@ & %+5+5 0@   ?3?3999333310!##33k<:)@ iY kY?+?+?99310!#! #"'5326!1?^J;4=O]m7 V{0%+}2no3}&\7)@   iY?+?3939310"'5326733?3%qV[fk=^-S)d?/9R+꺪Phs; 2@   "iY?+3??3933310%3#!3!3۶+@ iY ??39/+9933310!##"&5332673ϸh޸|_X5'Gvu6 1@  iY?+3?33933310)3!3!3DHJ;@   " iY?+33??33933331033!3!33#Ǹ9;! U@1  iY :    iY kY?+?+9/_^]^]]]+933310#!!5!3 32654&+!I  #z U@1 iY:  kY?+??39/_^]^]]]+9333310#!33 32654&+#3}P 粦"xV J@* iY:  kY?+?9/_^]^]]]+9933310#!3! ! 4&+ f'{=Y@5 iY:0@ iY iY ?+?+9/_^]q^]]]+933310"'632!"&'53 !5!&$ۧL9qeVc 9)NVn##_@7     iY :     iYiY?+?+??9/_^]^]]]+93333310! !#3!! 32#" ^P2XqnPV5Lr,&%)-V G@%   kY!  kY ?+?39/_^]+3993333310 #.54$)##"!3ݷq^2ΞJ^^\Du\"L@(!#$ ]Y? aY]Y?+?+9/_^]+9993331076%3>32#" !"uw荐 :m)Io#o4-/& Qaf}jG8J 1@   ]Y?+3?33933310%!3!3!3۴/ٵJNJ;@  "  ]Y ?+33?33?9333310%!33#!3!3۲FٵL{JN%#J i@@ ]YE `p ]Y ^Y?+?+9/_^]q_^]]_]_]+933310! )!5!4&#!! 7/A:y/ ZPJ i@@  ]YE `p ^Y?+??39/_^]q_^]]_]_]+9333310!2#!34&#!! #3b7 w JYSJTJ ^@9  ]YE `p^Y?+?9/_^]q_^]]_]_]+9933310! #!34&#!!26bF>|6ɤJXT\;^]@9  ]Y i 8 X o       aYaY?+?+9/_^]q]q]]+933310"'53 !5!.#"'>3 ^zPi3@L ;>g6"?^m@A     ]Y E      ]Y]Y?+?+??9/_^]_^]]_]_]+93333310#"'!#3!>3232654&#"?鴴򎝝' J7!J =@     ]Y ]Y?+?39/+39933333103#.5463!#!)!"9~η sw wPjZq&Hj . %+55N'@J%()!_Y!! ]Y!!! ! !!]Y?+??9/_^]]+9/_^]^]3+39933333310"'53254&#"##5353!!3>321P97:w}v 1sʐBׅ=[N\L!&v K %+5q^_@: ]Yi8Xo  aYaY?+?+9/_^]q]q]]+933310"32&#"!!3267{T;5u ]>x!(!4%;hy^VsL,&j %+55sMPJs@F ]YE `p^Y]Y dY ?+?+?+9/_^]q_^]]_]_]+9333103 )! #"'532!4&+326F``vCk%P}ㄉcYQ\Jq@A    ]YE   ^Y?+??39/_^]_^]]_]_]+93333331032)!#3!3 54&#J\ }J;J7ZPLs@A      _Y    ]Y   ?3?9/]]+9/_^]^]3+399933333310!4&#"##5353!!3>32wN 5lՇX@UU^#!&v? '%+5&\6 # %+5RJ 0@   "]Y ?3+?3?933310)3!3!#-<JN'@ iY?+?9933103!#fm-/P'@ dY?+?993310!#!3PBJ?Vs&:CR&" %+5+53!&ZCu%) %+5Vs&:vR@ "&I" %+5+53!&Zv! M)% %+5V)&:jdR.&+ %+55+553&Zj 2 %+55s&<CR &%+5+5!&\Ca! %+5Ru(@/_/]]]399105!R\ՠRu(@/_/]]]399105!R\ՠRu(@/_/]]]399105!R\ՠ9NK@.  `H/+3]/]3]333210!5!5!5!NRR9N ?9910'673% b8B%Z yN?9910#7?4|F ?u@/?/]9910%#7f0C$P ?9910#&'7%B-m^e@   ?32910'673!'673j.C$ f6C$j`Sr@   ?32910#7!#67=1A#;1B d4]'@  /?/]33/3910%#67!#67B0A%;0>h&h 9@    ??9/333933333310%#53%31J13__{i@8         ??99//]3339/3339333333333310%%#553%%?_21X++X12_+{$|d   /99104632#"&tonuwlnuzzz "&@ #$ }Y  ?33+3391074632#"&%432#"&%4632#"&A<=DD=;B}$?399?3??99//339993333331032#"#"&546323265#"#"&54632 # 32#"#"&54632GNNGɝGNQMNGɞ՝+GOOGɛLJڧH"JKHH Rs+$@ 0/]q/993310 RX)JKPs)$@ 0/]q/993310 ' 7)ZeK_^Jdh']!%+55y??3310 #}Jm<@"    0 `   @   ?3?]q2399333104&#"#3363 LLNoZ|f IUEe|XeP\#a@7  wYtYI?_o   uY ?+?9/_^]]+9/3+393333310!!##53!!!!6ʲ@ 'DJ!@R  "#wY   wY/?O sYuY?+9?+9/_^]q33+3/_^]3+39333333333102&#"!!!!!!56#535#535ƥ@ca?MPEq-+ )i@7 !%  %*+  _Y!kY)kY^Y?+?+?9/+9/+333/933333310%267#"&5#5?33#!##! 32654&+f%QCpv}?i5?5µT} RIՉVLR!/y&@$ '( /wY   wY/O_ /_ ""tY"tY?+?+9/_^]qr33+_^]3/_^]q]q+_^]3393333333310 !!!!327#"#53'57#5332& KL#Ǩ.((͢L+y8>,BA **N_T .M@*'",  ,/0)    % ?3?3??99//3]39333310 # #"&5463232654#"%"&54632&#"327՞+XVSYg[#SOgXiJswwsٲ%k#ko$F@!#  %&#     /3/399//3999993333310%273#"&=56746324#"6}iPpNrxεP{A>wөy&ꐟNgx!UgV'+u@A "+"( ,- %mYmY ((()lY(?+33?39/_^]+9/_^]+99933333310!###33&53#"&5463232654&#"5!^"PZZNNZYQ`mL3quuqrmm#B@$    ?33/3993333310##5!###33#7#s!T{Ǻcnn+T+/NvfH4@  ! /?/3/299//]39310"&54>32!3267.#"y1RQHbٓ2Xz#5Fi)|5BuE'd&{>j ?555#''>u ?555G'&< >} -?555f'N'>u=- ?555b9'A@"%%() !dY ]Y]Y?+?+9/+9333310#"&546327!"5>3227.#"9챰Y.:;=C#}Pcaa74QEL*(!:Vl{t~)} '@    iY?+?999331073!!&)͸'3+CqEoȂ%%@ iY?+?3993310!#!m`^H @@"    iY iY?+?+9999933105 5!! !HrH9q+r f+"@/_/]399105!f% @  //99//39310##5!3s% ^w-+J@% #)) ,-# &  @  /]]3333/3339993333310#"'#"&54632632267.#""32654&-|}y|?l41kEM_^?k51lDL`_φ԰ӮWa^ZiQQelY_^ZhPNj @  ?2?393102&#"#"'5325S.;8O==>崹l`/#/X@9(01'/$ *** ***/ /]3/]3/]q3/]33993310"56323267#"&'."56323267#"&'.N69lDvSI_/5}9iCoXK\067j?lbAa5<|3hEvOYW@9n#B9m%A7m)F3n !%f)G@,  O //]33]99/]]393310%7!5!!5!!!!!iTy3l}ߒ=f+ A@&  0p/_/3/]3/]/]933310%5 5!+;;fmf+ I@,  0p/_/3/]qr3/]/]933310 55!f;BofXj= '@   ?/999333103 # jN>N^5!4&IL '%+55#&IO %+5 &@  _/]]22/]39910"&'332673H [qgc ْhRXbbJ @  ]Y?+?93210"'532653-^@ECNIUW{ @  `  ?]9910>73#' V1bB35Ho;u @  `  /]]9910>73#o6a3bT3B?<{! "@ o_/]]]9910#5>734c2d;:8=J @@     ??9/]33399933333310##5!533!547}p}ZkCͿkd=7B@'  o !?3?39/]]3993333102#"&'532654&#"&'!!6NJ)86\mlc6K"!As{"&QYOUp 9J @ ?39?9310!5!\;]J{d39"-M@*+& &++ ./ (((((( # !?3?29/]q3999333333102#"&5467.54632654&/">54&h~JTGF=E2&1%  -, 48!59/33/33399/]]q3_]]/3/33/33/39/_qq3993333333333333333333333310!#%5!#533!5353!5!!5!5!#3#35!#35!35!#35#3#3#"&546323254#"%32+32654&+32654#"'53253T/0momImmmm0oowoooomm~smp.,=.m^{B.$*/;J1%Z^4+V}i0oo/mmmmmmoo;mmJoooo/yhIaCS1BD5QYb" "+%J fVr_cT*,@ % +,((""//99//339910 5467>54&#"63232654&#"TV,AgIOGRZ?>1HT;GFBIHCHEVW/2A1R~X8*P:/5K6DpJ;?HI>@IHc!&7L  %+5N *4g@7 2"*((+" 56+/)%**)dY**%^Y%%/]Y%^Y?+?+9/+9/+99933333310!"&547654#"'6323 4',546323%.#"jD,0'^an+`NY_F94t=ooR++wwCb;,ǑދkWH(@  kY?+??999321076>32&#" #3?E9L]@:$#-E}##۟"l2Ka/J(V@+ &   &&)* ]Y#]Y?2+3?+339/99333333310"&54!57!##"'#326=332654'7p˾EG{lt\hj[tijNH븸έ}{u&0vT@ &N %+5+5!&Pv ^,("%+5&$X; %+55^\&DX ,&%+55zG @s7 4@   o  @H @ H /++q3]2993310#"&546324&#"3267}hgxzecrB13@:93@cxudduud8;;86==f,(@ ^Y ]Y(]Y?+?+9/9+10.#"3>32#"&54!&#"32>5i%$#[7? :j瓸ɶWTpa2aQ;vk]L M]Ŭ۟'|+BJ.|.j&I'IL-,=%h=%+5+55&I'IO-,1%h1%+5+5}q ?@"!"  iY iY?+?+93?99333310! ! >5332#"aEED?h]~qjh|'+'$*q+#R@-%$%   !]Y ]Y?+?+93/_^]^]99333310#"&532>5332654&#"h| lB2; ~jEÞ'ҋ +IDCej'8@    iY ?+?39/3?99333310>53! 533265RM!ԹŴ  JľZ@2 P     ]Y?+??39/39/_^]^]q99333331032653>53#'##"&5Xw}PI  2tH?:y OVM!C!vRw-@  /_/]qq]29/310#'>54#"563 w oJX5-%L׌&m .0Rj 1} @ P  /]3104632#"&1?,+?;/0;<77<5=<s&(CR &´ %+5+5`s&CfR& %+5+5q!&HC´!% %+5u!&C %+52P@(+("+( 00(34))iY-%%iY ?3+3?3+39/993333310"'632!"&'## 32.#"3267332<_,I~tKIs|J,^<˺>|1ḅ%+Ta2222uSxT+'%=LE,!-J"+@#$  ???33939210#3367673363#&-"u6XdjKa پ}ioJlV@%acYOPKr@@ kYiY: kY?+?9/_^]^]]]+9/_^]3+3933333310!53!!3 )!32654&+:b5gӬ`5gu'z@H  ]YE `p   ]Y ^Y ?+?3+39/_^]q_^]]_]_]+93333310!!! #!#5353!2654&#Z5)J˥\YYQ%!c@: "#iY: iY iY?+?+??9/_^]^]]]3+3933310"!!327# !#3!%2.G ]q V o2ڵJi):"mQV/N^3%^!@L  "# ]Y E       aY aY?+?+??9/_^]q_^]]_]_]3+3933333310"'!#3!6$32&#"!!3267 紴 ᣄ5r Y<=J7;4%w T@.       kY8  i    ??339/q]]q+39_^]93332310!####3 !'&'ꐨbcIP: .\\JBƖd'J v@M     ]Y    M ] }   / ?    ??339/]qr_]q]_]_]q+39933310 #####!&'#Ӹlqƹc  JJ+g#Dog@9     iY8i0  ?3?39/]q]]q+299333333310####!#3!3#!'&'kal>J<AVVVjJJĘ\^1J@O     ]YM]}/? ?3?39/]qr_]q]_]_]q3+339933333310 #####!#3!#!'&`Ѷlk͸߰cs($8 :#JJ5ySY"g@< ! " #$ lY: &""jY?+99?339/_^]^]]]3+3993310#.+##"#>75 !7_sf]W BcRQa?"ć.brgKo#Mia+J)]o?śM J #@O!"##$%`Y#o-=]o   " "]Y ?+99?339/_^]q_]q]_]_]33+39333310#.+##"#>75!SlH/!7OF BO7#6NqYJi2Ni>LUDBXPb9 bi$'z@I&"!'%'"# ()!kY!iY'!:! !!!!!$#&$$&jY$?+9?39/_^]^]]]33++3933333310#.+##"#767!#3!5!N`sd.$BeV~s+'[Q#\n$oM;n](Lb?;%V㇦FJ%(@T&'#"((#$)*"`Y"]Y(""E"" """"""%  $'%%']Y%?+9?39/_^]_^]]_]_]33++39333333310#.+##"#67!#3!5!;SkH/!8QC DQ8"-%ϰ+Ji1Nh>LTDBVPt(J7`i=JBK@U( >6ABB;,;0>!E!0*LM0*..833/3 3*AkY:*H*$lY;*iY#?+?3+.39/_^]_]q+9_^]22/993333333333310327632&#"#"&5467>5!#532654&#"'67&'53>32&#"TX`xxADFBlmhź=ןmcZ3\]A70',o0Ŀ`v652'3 {j{@)D 7//7D>)GH 3443]Y4i484X4o4444 44>,&]Y&D>BB@ H>>9^Y>?++322/9/+.39/_^]q]q]]+9933333333333102&#"32632.##"&5467>54&+53 54#"'67&'53>:*+/e-z҂usMWnK{)Z+rjw7?vkVHYPu M<k8%d.<2* ){uz][`WF6R2pUmu} Y@4iYzIo  iY  iY?+?+9/_^]q]]q+99333310! ! 2!"!._G>b^ D nheqM qh^ m@C]Yo-=]o  ]Y  ]Y?+?+9/_^]q_]q]_]_]+99333310#"&532267!"!h|  -'ҋ +TFHR"@ kY?+??93310"#367>32&=N4MF!E;TnY*W8+hXBLT"@ dY ??+?93310!3367>32&#"B !6op&.).9r)5_k RVRs&}sR!&%%+55+55L!&~so& %+55}  .H@' '!.'/0.  iY iY%*]Y%?+?+?+?3?9933310! ! 32#"%33673#"'5326?ZE,'EmD N۾+ENJ7BUw*9rljs*(''GxQs \fq^&R\w "1%+5}-(Q@* & " )*" $& &jY iY?+992?+3993293333310#"'$%632>32654'#"'w|-|v .)úI6i$¹nqu+oo(95+ll,u*0&V*+((XV(q+M@( )#!! ,-&#))]Y ]Y ?33+33?33+33933333310#"&'&547>32>326'#"&' @89? >96B V <5f=46= w'&5.-8$(!$6**8&;*"J<\U>*!"+{DEW@RIMC6FM*%M; 6XYIUHU@5 HIUIU9     @9@iY'93iY-3?3+3?3+3/_^]33/^]3399//++]93333310#".#"#54632326732#"&'632!"&'# 32.#"5>54.54632Wxc*j|m:qwN#^;>YΣ&5-9D#*#tnn%-%J?@IJ'!-Z>Vb//0.vUvV>Z-ZPuJ2&'Fo *?N@JCF@F(,"F6OP HLHL@C HCLCL 2+,,55 555552:::::: :@ H: aY% aY?3+3?3+3/+_^]]q33/]3399//++9+93333310"'#"32&#"!2673 #"'>32#".#"#5463235654'&54327a/pS?x*;[Erm)9rGt}'G[;){?RWxb*56zp:pwM}ww11b9DE %' + 4d%/T4 $*$7>nk$,$QtH(:,NF &i hf>&@4 %+5+5-&j h  0$%+5{/@   iY jY ?+?+?93310"327# 4$32&HoGGK'jnXVPq^1@  aYaY?+?+?9933310&32&#"3267#sM=5dBY)*4dhu7@     ?9933333310'%7%7%{D!Ey!FC7C@ubw=E¦uu0@   @ H0 / _  /]2+993310#"&5463!>32#*05)*6,03-,6-2455+//158*8@   @ H /_/]33/+]3/3991027632#54#"+5xQmzj+dxVh;:kn!d$+$9@  /9333104632&F9/3$w9H)':$L:9@  /9333105654.54632w$4.9D:L%9')H) (6DR_m@iP4H, B&:V^&,c4k no-&44)"00)d^Wkk`ZggS`IB;PPE>LL7E)`EE`)P     ?o/]2q2/]]3q29///333q2333q2333q29333333102#.#"#62#.#"#>2#.#"#>!2#.#"#>2#.#"#>!2#.#"#>2#.#"#6!2#.#"#>]qO?#&*-O;_;;;;6@3P3333.6-&..&-6  ?/9////////]]93310#67'>737&'.'5467'67".'7&'7 F$a5; Ia4#GA݁hBO݁E?軋Ek(8PC{Lh&ZC7#BO݁GA܂ Ia5; F$a5[8D.^3DuOW.FcB=FK%b"]@3    #$ " " iY?+???399_^]22/^]39333333103333##47##"&'332673Ǭ  $ɔӞ I ]nic ەQB+lN]]1b@7      ! "_  ]Y ?+???99/_^]]33/]3?933333331033##?#%"&'332673X Lݼ} \qic J_N{hJgS]]/z@G iY iY: kY?+?9/_^]^]]]+9/_^]]3+3933333310353!!3 )#32654&+/PLmPѽ`^>{T@V     _Y]Yo-=]0o   ^Y ?+?9/_^]qqr_]q]_]_]+9/3+3933333310!!! #!#5353!2654&#b/4'!ɤ[ZYQ}Y@-    kY  kY ?+?9/+999999333333310'+#! 327'7654&+}riuib_8fqv8XVF{^(]@4 $!&&!")*!$# ]Y]Y?+?+??99933333310"'##33>32'"327'7654&w @npjDr,&wp}] =6YQT۸# Tg/ E@$   iY    iY ?+?9/_^]3+39333310!!!##53qZ}NJ G@&   dY    ]Y ?+?9/_^]3+39333310!!!##53!NX#݋L@(  iY   iY&iY?+??+9/_^]+993333310"#!!63 !"&'53 4$7^ZRf_x>XUF{w  1 JJ@'  aY]YaY?+?+?9/_^]+993333310"'53 4&#"#!!63 Njn~ N< R<  <=/J L@*    " iY?+??3?339933333310 333 3####N//°fű<<<=JK@*     " ]Y ?+?3?33?99333331033 3#### 3;gȮb%%;Ja{--5N=F&|^3- %+5D=^&| /)%+5=E@$       "iY?+???39393333310%3###373p~ /FVJ?@!    "  ]Y?+??3?993333103 3###37+wXJ_}-JP@(     ?3?39399999333333310#3733 ##}}}Z^}k+^FHJI@&     ?3?39999933333310&'#3733##N%s7N)JyJl3/X@,  iY  ?3?3939/+9999333333333103533#3 #&'##/Z݃{Ǯ^f1P@)  _Y??9/3+3?393339333333310353!!37673 ###w@,^D}\[.s+km D@#     iY?+?3?9393333310!3 ##! X+%J 6@      ]Y?+?3?993310!3 ##!%+J-Z@4    iY :      "iY?+???39/_^]^]]]+93333310%3##!#3!3%Vj Jj@>   " ]YE   ]Y ?+??39/_^]_^]]_]_]+?93333310!33##!#bTJ7N{Ju U@1   iY :      iY ?+?3?9/_^]^]]]+9333310!#!#3!!uVjJ c@;   ]YE    ]Y?+?3?9/_^]_^]]_]_]+9333310!!!#!#bTJ7ɔJJ) R@, !" iY   iY&jY?+?3?+9/_^]+93333310!#!#!63 #"&'532654&#"ݶXL1POF~+}a כ1 JR@-  aY ]YaY?+?+?39/_^]+93333310%#"'5324&#"#!#!632ÄcjoG8yM:;<=3NJ' })5m@;30$3**3!$673- ' '-kY'' '' iY iYiY?+?+/+9/_^]+999933333310327#"'# !2.# 327&54324&#">rBUN=8]fH;\1f2?2*P^ǰúdXYdZNapVd$Vy#  _RAq^ 4y@(3+%.+#%56#! .((dY(((@ H(( 0^Y ]Y!]Y?+?+/+9/+_^]+9999933333310>54#""'#"&532&#"327&54632327C:BQEH^|hvz_M'FA>i[2>B3,\/*kxfO(/ ۬~=}=&&|' P#%+5q=^&F| R" %+5\ 4@    "jY iY ?+?+3?93310!5!!3##7J7)J 4@    "]Y ]Y ?+?+3?93310!5!!3##y{<J&@  ??3/39932310#33>73bRO =RN_9@ZB@"   iY   ??399/3+393332310 3!!#!5!53D}-ӹ/9\1J<@ _Y?3+3??3993332310#!5!33673 !bTN}G8O@'    iY??39/+339/9/933333310 333673##u/}t}sGzqZ:JT@)JQ@(   ]Y  ??39/+339/9/9333333103673##5#"&5Lyp~ny Jn)TW-@   iY ?3?9/+99333103$32#4&#"#Ǹ߹|f\-vv"2;NJ-@ ]Y ?3?9/+9933310!4#"#3>32_hcl5@+JD;f7P%s@@#$$&'##iY#z#I### ## iY iY?+?+9/_^]]]q3+33/_^]933333310473;! !3267# "&"!7o")H(4_qݏ`M:-CeGOh2 )"aKv-\$f@7  "" %&!!dY !!!!]YaY?+?+9/_^]_]3+33/_^]9333310"'$5473;>32!!267"!4&PhPdd[ 1G4%Eem *' ݟ7P!(@G % !&&!)*%%iY %z%I%%% %%!""iYkY?+3?+?9/_^]]]q3+33/_^]9333333310$"&5473;! !3267#"!4&o"P'5_P` ](vwM:-Ce?Wn2 B-\ 'r@>   %% () "$$dY $$$$!]Y]Y?+3?+9/_^]_]3+33/_^]?93333310&'$5473;>32!!267#"!4&hPddH[J 1G4%Eem *"DRb,b&6R@ %&+5+5&6 %+5'F@$    kY iY& ??3?+9/+393333310"#3737 #"&'53254$d_IcS~J{q<Rכ1 5JD@# ]Y aY?+??39/+393333310%#"'532654&#"#335oˈc/lDQ_5;<%HJ;@"iYiY kY ?+?+?+?933310%3##! #"'5326!Ǔӟ1?^J;4=O]m7 VJ;@ "]Y]Y ^Y ?+?+?+?933310%3##! #"'532!𼃶}`v="l#{a %U@0   iY:  iY&??3?+9/_^]^]]]+993333310%!"&'53 !#3!3%T}L{1Vj jJa@9   ]YE    aY?+??39/_^]_^]]_]_]+993333310"'53265!#3!3ц_ni}tR :;J7^@6    iY :      "iY?+???39/_^]^]]]+933333310%3##!#3!3%ɖӠVj'Jn@@    " ]YE   ]Y ?+??39/_^]_^]]_]_]+?933333310!33##!#bT~J7N{J;@   iY  "iY?+??39/+9333310!##3#"&5332673ϲh޸|_%5'Gvu69J=@   "]Y  ]Y ?+?39/+?933331032673##3#"&5L\enlJp7>QG8BE@$  "iY?+??3?39933333310!##!3!3##47#Lǔբ]wRJB@"     " ]Y ?+33?3?99333310%6733###.'#3.較?4%mtN{;^-wJC]Rb,b&$6=R@ %&+5+5^&D6)1%+5)&$j?R@  %#&+55+55^&Dj&8%+55^^b&(6R & %+5+5q&H6 ' %+5yjE@% iY iY iY ?+?+9/_^]+99333310"5>3 ! 5!27!}ڀLr/+T,"pqyvFbh^Hyj)&jsR@ - %0&+55+55h&Hj.%+55)&jR@ $%'&+55+55&j %%+55NF)&jR@ =&(: %+55+55D&j$6%+55H;H@&kYiY kY?+?+99/+3933310 ! '53265!#5!5!dbA]B O00ФJK@'  ^Y]Y ]Y?+?+99/+39333310#"'532654&+5!5! ̢xFɐ|HV}`&MR @& %+5+]5uj&M7  %+5`)&jR'&$ %+55+55u&jB  %+55})&2jR@ -&*%+55+55qh&Rj *%+55}{qh^|})&{jR@ /&,%+55+55qh&|j+%+55=)&jR1&. %+55+55;&jSŴ+%+55&M/R@& %+5+]5j&\M  %+5)&j9R@ ,&) %+55+55&\j * %+55s&SR@ *&U & %+55+55!&\S M!' %+55)&jhR@ )&& %+55+559&j % %+55 /@   "iY iY ?+?+?93310!!3##GqJJ /@   "]Y ]Y ?+?+?93310!!3##J{)&jR-&*%+55+55&j) %+55/j&} %+5jNJa@5    dY   ]Y dY aY#?+?+?+9/_^]3+3933333310"'532=##53!!!!3.9b\+jkJ1bZ_@8     iY9h0 ?3?39/]q]]q3+3339333310!3 3!!# #!}3wfgu9}wV`?L{%J]@9   dY/? ?3?39/]q]]33+339333310!3 3!!# #!s c`{b1J; :@ iYkY?+?9/_^]+9933310!33! $#";FaٽjJyq=G}"Z@1 ""#$piY# kY?2+3?9/_^]+/_^]99333310"&54$!3332653#"'#"!265L("fsֹbp"ϻzj{m̧tio ,O@)*$$-. (]Y!!]Y ?3+3?+?99/_^]93333310%2653#"&'#"323/3!26754&# ri.S}i< iꈁ3WknV)  0MUNT#XH*\@2" +, p  kY+ kY%iY%?+?+9/_^]+9/_^]9333310#532654&#"'>3232653#"&'.ǿғca\abhztmj{9B{JNĥ3Ӑ}x)̓N^%R@+ !!&' ]Y&]Y]Y?+?+9/+9/_^]9333310%23# .+53 54#"'>32Jײ~s!NO;Rnjv3IdY$"'%9}dH$W@/ %&kY " ""kY" iY ?+?+?9/_^]+9933333103##4&+532654&#"/>32 ¸ߠgk-/ebj{8C?T4lpݴ6wm"̓s);J@@"]Y ]Y ^Y?+?+?+/_^]93310323#"&5! #"'532!fsϴ`v="l#|59a fe@:  p iY :     iY?+??39/_^]^]]]+/_^]93333310"&5!#3!3326539Ƕlonm-Vjσux)Jq@B   ]YE ]Y?+??39/_^]_^]]_]_]+/_^]93333310!3323#"&=!#b>hsϲ´J79}3nJ}=@ iY iY iY?+?+9/+933310!! 4$32.# 3265!b@Ty]FYa XaU0*'/q^E@% ]Y ]Y ]Y?+?+9/_^]+933310!! !2&#"3265!B"ݪ=ƽHF),PJ֜@@"   p  jYiY?+?+3/_^]9333105!!3253#"&5>5spsu))J>@   ]Y ]Y?+?+3/_^]933310"&5!5!!32653jjshk;̓}z9smd']@3%$$ ! !()%kY: kYkY?+?+9/_^]_]+9933333104$32.#";#"327! $54675. pbgjǶǯϺ\EKB5yl{\MǖX^j@@#   iY  iYkYkY#?+?+?+?+933310"'532=#! #"'5326!3;?.8b1?^J;4=O]m7 jkVjJ@@#   dY  ]YdYaY#?+?+?+?+933310"'532=#! #"'532!33232673#&'#57673\;:ZF!p$GC@(*] dL%IE>(* \ edbfo\yb6o60w4;DhxcE$.2js$/1jsBbSQ%+55s&$'dK/R@ &&(%'!%+5+5+5^!&D'dK&,%ߴ?9%+5+5&$xR@!% &+q55+55^&Dx19%+55&$yR@ % &+q55+55^&Dy08%+55X&$zR@!)% &+]q55+55^&Dz9A%+55^ %2@ 43/( (((,& &&@< H& 0 "  iY ?3?9/+9/_^]3^]/^]]q33]+q22/]]39310!!#3 '".#"#>3232673 332673\;:ZF!p$GC@(*] dL%IE>(* \ elOkbXm ;DhxcE$.2hq$/1grE<@A^ &D{@H%+55N&$'N1bd@&"(%%+5+5+5^&D&Nd4:%)1%+5+5&(d  %+5q^&Hd " %+5&(cR@&-  %+5+]5q&Hc @) %+53&(RR@  &! %+5+5q&HR  %1 %+5z&(tR@ % &+q55+55ql&Ht  " %+55N&(uR@  % &+q55+55?&Hu@ " %"&+55+55AJ&(vR@ % &+q55+55q+&Hv " %+55b #2@) 43%'**.:.. 0*@** *   H @2 H   iY: iY iY?+?+9/_^]^]]]+/3/++_^]33^]r]99933310)!!!!!".#"#>3232673#&'#576731Ty$GC@(*] dL%IE>(* \ edbfo\yb6o60w48$.2js$/1jsBbSQy@* @?136:*::6 6@.2H6@ H6 )! H@ H,$ iY iY?+?+/3/++_^]33++^]]99993310! ! 32#"".#"#>3232673#&'#57673_G>b|g$GC@(*] dL%IE>(* \ edbfo\yb6o60w4nheq,&%)$.2js$/1jsBbSQ73'673#dpcrae3w0GPI6Q{gK[eA:Eg[plb 3@ @ H   _/]]33/]99/]+10#&'#57673%#&'53farjid5q3>byV9FAe`F=JY[suXj d@!@ HD`pH@ H   _/]]33/]99/++qr^]+^]29/310#&'#5>73#'>54#"5632dpcrae3w0GT ;>c/8K[eA:EgxfO %>Tf&K@1 @H @ H  @ H 5"" """_/]]33/]]]9]+2/++3310".#"#>3232673#&'#57673-$GC@(*] dL%IE>(* \ edbfo\yb6o60w43$.2js$/1jsBbSQCBq5@"$4  /  _/]]33/]3_]]10#&'53 332673bwV.O9lQi`Zm ^qeh G>ADqf@$H@ H */H$H@ H/_/]]33/]33/+++r]r29/++310#'>54#"5632 3326731}T 9>a%$>lQi`Zm yc)\ #=P G>ADf $E@. @H @ H  /?!/_/]]33/]3]]2/++3310".#"#>3232673 332673-$GC@(*] dL%IE>(* \ elOkbXm 3$.2hq$/1grE<@A-=q@   //39933104'3#"'5326݋id@7#5%3gw[js /j @  kY#/?+99310"'53253;?.8bjk3\&7zF %+5!F&Wz %+5{)t@B'  ' '*+ _Y ]Y  $]Y?+?_^]+??9/_^]^]3+3999933333102#"&'###5353!!36"32654&o7K oǦ\POxׇ=qqh$-t@> && ** ./ %%kY: $ $kY &kY?+?+39/_^]_]]+99/9333333310"#.5463! #!!2654&+!2654&#5} &'g=1B} /nxj}{#E@#! ! !$%  ]Y]Y]Y?+?+?+?99993333102#"&'##!!36"32654&o7^V oǦ\POxqq J@*  iY :     kY?+?9/_^]^]]]+993331032654&+3! # qż  { u9@  ]Y ]Y?+?+?999333310"3363232654&#" o⧓(qq3н?&@ iY iY?+?+9310 #"&'532#"'6D[qWJv!:<5PV}$G@'& !!%&kY/ iY iY ?+?+_^]+99333310"327# 4$3254632&#".9]p?|tn~==19`JD):"hTch1q^!:@# "# aY aYaY?+?+?+99333310"3254632&#"&#"327f 8Mm~54&#"vĬhNLhR`mլ{ªZMc.@+=LAEk[u ҳ~E-֡{ S@0   iY:  iY iY ?+?+9/_^]^]]]+9333107!!5!!5!!{yT1Ϣ ȢJyjof']@3%$$ ! !()%kY: kYkY?+?+9/_^]_]+9933333104632.#";#"327! $54675.؄dXkjƻ߸ݿ`MK}I4}h{kZϜQ@1   iYI  ? _ o    iY iY?+?+9/_^]]+933210"'53265!!!!\B1*3H91RSUX}'Z@2) %%'()kY/  'iY iY #iY?+?+9/+_^]+93333310!# 4$3254632&#"&# !27!BtW钆n~;@1:`F 3%&cV##clT#B@"!    !  iY?+?399333332310%#"&5436734&'32DEjnR#"''E݆MyvUhs6AM-?:$E@$"  %&]Y ]Y ?+?+???993333310%2653#"&54&#"#33>32ykt 2c}bA8Z@UU@ iY ?+?993103267#"&5oJS,^p8cb tFoX@,  iY nY nY?+3?+39/3+3993333333310)57#53'5!3#b𬸸j' )jj)'<@     kY?+?3?9399333310 #&&'#3676>32&#"V=p9B,O;iT>(*0"<-=QӈHL2MA(63A@"      aY?+?3?93933333103?3 ##32&#"`=F_D}CB/;/2NTs+mm6A D@&  _Y/ ??9/]]3+3933333103###533b\+ՇV!&d@(# '(@ H""  ]Y ]Y?+?+?9399+9933333210#''7.#"56327327#"&'&'# /'D;>5DCm3&n/$%2CJZ U!P5A=.( VcDB96 J[S~u$>@# #%& $  iY ?3+3??339993333103265332653#'##"&'##"&5qvw 3w- :~tJWedhbj N6@   iY?+??39999333321033&53###"'53265-  B1*3H9Gs'B9JQ%SUL^}{}'E@#"""() % %iY iY?+?3+3?939333310! ! >32#4&#"32#"O6#9{¸vl'mqieXc>?,&%)q^%G@$!!&'  $ $]Y ]Y?+?3+3?939333310#"&532>32##"32654&# 5vف5W>G'Ӌ ,KHIZF@#  kYkY?+3?9/+9/933331032654&+7 !###"#.5463#Ķ$騹5} ׍Rg=1B}{ -J@(%  ++./ aY!]Y(]Y?+?+?+?999333102&#"3>32#"'##"32654&CB/;/2 @nw 裑6A=N)ZPҟ)N==#3N@&   iY  kY  ??9/+39/+993333331032654&+#33 #۲Ѹ+~Eqep\`%;@ &' iY#iY#?+?+93993333104>7>54&#"'632327#"$`R}7:ϟ>E{cr?4M_GepNRʫK:R^Cn~a"-\m^#=@ $% ]Y"^Y"?+?+99993333104>7>54&#"'632327# \>ftpg>;~ls0J/LnX4EO=>GFJLjU<)@?-PRXEJ^p"O@.$ #$]Y  ]Y ]Y?+?+3/_^]q+93323310"&546323267#"&5";54&{zJS'em4d,$eO2Vxmnvoda 51RH?!FP@(     dY ]Y aY?+?+?+333/9933333310"'532=# #5?3!!3267C2%$-AKJ2FJ5FKR'[^ 69  ’N_IoWNDW@0   lYiY  iY?+9?+99/_^]3+393310!!5!3!!!5!y5 lBФ%PsJl@=   ^Y5EedY  dY?+9?+99/_^]^]]3+393333310!!5!3!!!5#uIT =w{H;H@& kYiY kY?+?+99/+3933310! '532654&+5!5!T|dbZrǃO00qdF@% kYiY kY?+?+99/+39333105!!#"3267#".54>7]dc\ڈ{ގ%c00,#ỏuFJI@& ^Y]Y ]Y?+?+99/+393333105!!#"327!"547}Fx̷ǃ}VH9J$f@7""%& ]Y    ^Y]Y]Y?+?+99/+3/_^]+933333331027#"&54632654&+5!5!#"zйƾxv'lgmJ54&#"'6323!!!57!81zl]K`+34}9g`wZZYgrDCyǬV[!C1 }H;C@# kY iY kY ?+?+39/+933331032! '532654&+#5!Vdbun̈O00"DJC@" ]Y]Y ]Y?+?+39/+99333331032#"'532654&+#5!/򄷽ᄋGVmlmjJXF!P@(  "#@  dY^Y?+?+3399933333105#5?3!!#"'532654&'.Gk=*6؀|caIVHEA?jEXXJ)%+5+5q_!&G']L{@72&'%X#*9%+5+5{&/-1 %+5&/M1 !%+55&OM W %+55{&1- c#%+5&1M c/%+55e&QM S 0%+55&$L/m@ %&+5+5^!&DL2-%+5&,Lm@ & %+5+5c!&L  %+5}&2Lm"&$%+5+5qh!&RL $%+5&8Lm@ &%+5+5D!&XL ! %+5&8 LR@!&-,%+555+555D&X Lu@ 0/ %+555J&8R&@ !0!@!!&$.%+555+q555D&Xs@ '1 %+555^&8 KR&@ !0!@!!&:3%+555+q555D &X Ko=6 %+555J&8R&@ !0!@!!&.%+555+q555D&Xu1 %+555h^W@5    ^Y    / ?   aY]Y?+?+9/_^]q^]+9333102#"=!.#"5>267!Xj[^ m-' !&$ LR@ %&+555+555^&D LJ8&%+555&$ O %+55^&D NJ54%+55&MR U@%&+]5+5^j&M״>= %+5}#l@= !# $% lY #iY/  iY iY ?+?+9/_^]+9/3+3933333310!3## 4$32&# !275!5!5!BtWF -͒%&cVVT#q^".@K!-&" "!/0   ^Y  / !  *]Y #]Y@H@ H]Y?+?+++?+?9/_^]3+39993333333310%7##"323733#!"'5327!5!7%26=4&#"oy uaSlū" *($FVf=!h};s&*LR@ &&z(#%+5+5q=!&JL 50%+5s&.LLR&ʹ%+5+53&NL{@  %&+5+5}=&2Q} )"%+5q=h^&RQ "%+5}=&2'MRQ}%@&)&"%%+5+5+]5q=hj&R&MQ&!%%+5+5H;s&LR@ '"%%&+5+5!&Lr&!%+5 &'= 4%+5 J&'] >%+5q_&G] X#*,%+5};s&*vdR@ %&%!%+5+5q=!&JvJ D2.%+5\@4 iY:  iY?+??39/_^]^]]]+?93333310#3!332653#"&5^^`[aȳVj]fg^V;@  jY iY?+???+9993333102#33>$4&#"K[ LJX(qjˊ Ns&1CfR& %+5+5L!&QC %+5s&$sR@ %&+55+55^!&Ds4&%+55>&$R@ %&+5+5^&DT1)%+5s&(sR& %+55+55q!&Hs+% %+55>&(bR@ & %+5+5q&HV ' %+5ds&,sR& %+55+551!&sV %+55>&,\R@ & %+5+5E&%+5}s&2sqR#&'!%+55+55qh!&Rs'!%+55}>&2!R@ #&#%+5+5qh&Rm #%+5s&5sRz@ $ %!&+55+55#/!&UsH! %+55>&5}R@ ! %!&+5+5/&U  %+5s&8sXR&!%+55+55D!&Xs$ %+55>&8R@ &%+5+5D&Xy   %+5NF^(L@)##' )*'(('^Y((( ]Y  ]Y?+?+9/_^]+99333102654&#"'>32#"'532654&+5=~V=Z_򂂥[aΡӏqq(+ŭ},*͖|L+/%s&+LR@ & %+5+5L&KLN{@ /# %!&+5+533@  iY ?+???99933310 #33>3 #4&#\ B}-5]tdǶq'Ew%L@' ""&'$$kYiY?+?39/+9993333331026=3!"$&5%&533265! 엞1縠༹èc0ћyA]_*Jqh(L@'  ##)* &&]Y ]Y?+?39/+999333333102653#"5%.5332654&#"my^i i\yᓞ'3ٞKb'NjD&=}  %+5PjsJ7&$OR@ %&+5+5^&DO5&,%+5&(z{   %+5q^&Hzo " %+5}&2 L!m@'&32%+555+555qh&R Lm@ 32%+555}&2 Mm @ !!!&!-%+55+]55qh&R Mj!-%+55}7&2OR@ !&%+5+5qh&ROb%+5}&2 O'&%+55qh&R Nm '&%+55&<MR@  & %+5+]5j&\M  %+5P@)  dY  dY ?+?_^]+9999993333103632#"&''672654&#"?M|^&'JV7<3?6>?mrG<=o=m=-561^",o@; ++&&-.+ )  )dY ]Y#dY?+?+??_^]+99999933333310632#"''674&#"#33>322654&#"L?L|S(JVw 3oă4:>6>?mr9s=mJQY55561F$m@8 ##%&  #! !dY    @  dYdY?+?+33_^]+999999333333310#5?3!!632#"&''672654&#"Hk=?L|^&(KT84:>6>?VHmrG<9s=j55561qV'3T@,1&& +  +45  #..]Y((]Y?2+3?3+3?9933333310"323.533632# % 4&#"!2654&#"Vw  orr-" .9qqмVqV^(4S@+! , '2256 )]Y/$$]Y?3+3?3+3?993333333102#"'##47##"3 > 3265!"32654&qv  kr:kӑᐟ^ҡ#Ki^pq* %|ZϽ߿fd@7  /     iY  ?3?9/3+3_^]q993333333210#!###37&'3щӎ;>V(!l\N_;Tq^xcE }f&d@8 "$%$'($ '@")H@ HiY iY?+?+++9999933333310&'327#"'#7&4$327"&y'=@JI#zI[]p_b5C?NJ(p :"RbT SJqV"\@0 #$  aY aY?+?+?/999993333333310&'327#"'#&;#"զ9+7?#9Hr]] L2@;PP+ g =@    lY  iY ?+?9/3+3933331033!!!!#\ɳ9}f\D@%      iY?3+33?_^]93333103###!5!7#)-`Ϗ^7Y-^P#C^/h^2Q@*#0)034!,)0!&]Y!^Y ]Y ?+?+?+999933333103267#"&'&'&'532654&'.54632&#"%"'YF`E,|w~;=ptd>6b "XXJAZ:54&#"'>32׊J;DKj7sy8,6=Ѷ\3^-@   ]Y ?+?9/3933103>54#"'632FACȹ'750r˼V )@M %!%%*+iY  !!kY8!!i!!! !!)kYkY?+?+9/_^]]]q+99/_^]3+3933333333310#53! #!!!!2654&#%!2654&+Ǩ&/'^ ˆ}nxjO@'     iYiY?+?39/33+339933333333103#! =#533!26=!ܤ !͠AA·ӳif@W    !@iY: iY iY ?3+3?3+39/_^]^]]]3+3_^]93333333333103#3!!!#7#!73!3#et)''GXrF^8^8 qV#'+@O (*+'"&# $$#"+*,-*(&! '(!!(^Y!!!! ]YaY?+?+?9/_^]_]+999999/93333333333310&323!3267#"'"3&';q}R{>YXj[mkZ-kbZT`VL99m-' Nu6ʸO``{?@   iY iY"?+?9/3+3933333210"'53265#5333#^:GMdd{yr{m!Y@0  "#cY`   ^Y " ]Y?+?9/3+3_^]]+933333210"'53265#5333#4632#"&-^@ECNI%=-*??*-=UWC`_<66<;88}7-I@&)/# --./!iYiY+&iY+?+?+?+?9999333310"32>54.47##"$5!2373327# ʞ[\" 9奻G#; :G2*/C+\<[6]`pVancWQBq^ (K@'$* (()*]Y]Y&!]Y&?+?+?+?9993333310%26754&#"47##"32373327#"R su-8@&*e%՘n<,  /#pU!VK@%   kYiY?+?39/3+3399333333310##53! #%32654&+۲\\eq\/^R@,  ^Y bY?+??9/_^]3+3993333310!##5333>32&#"3d?eI8=:ump L@'       iY  ??399/33+339993332310!33###533!RƏ{y{'/1)J!U@, #  "#! ^Y ]Y?+?39/33+33?9933333310#533!33##"'5326?6!͹‰uEKJ2FVx&9Xo?= Nkk _cj6I\D}H ?55q=^<@     ]Y]Y?+?+??9999333310"32373#'#'26=4&#"3wsƤ( .!{^@J ?55{*E@$ ((+, aY]Y%]Y?+?+?+?9993331032&#"3632#"&'##"32654&EB/;/2 oo7ꦐ6ArqqPOxǼDf^(@ aYaY?+?+993310732654&#"'>32#"'V7271^r@";b^']@1 %% ()]Y  aY "]Y?+?+9/_^]+99993333310"''67&532&# 632"32654&}+ +@N T28bŽ~wRWiQbQa?~n+"4`iNs^M<09q',M@(.*#  -.']Y ]Y]Y?+?+?+?99933333310327# 5467##"323.5326=4&#"=1DI,/m  vw  j[!Vw*  .ym!q)K@'+'  *+ aY$]Y]Y?+?+?+?999333331032&#"#'##"323.526=4&#"H?/;/2sw  Ǥ6A( .y#!h^GH@h^W@5    ^Y    / ?   aY]Y?+?+9/_^]q^]+9333102#"=!.#"5>267!Xj[^ m-' !h^#+e@4-)((,-!aY ()) aY $]Y ?+?+99//3399999/+93333310#"#"=%.#"5>3273272>5s{KXj[m ,#>.RT9\F N ȅ-' Ŵ/zUK7NYX^D^D3^0{@E2%  ++/%12aY# /00/]YE0000000# ]Y #(]Y#?+?+9/_^]^]]]+99/+9333333310 54#"'6327327#"'#"'532654&+57O_?ԑ*o">.OW'1}?L/}v򄷽(L[U{UK7"._$$gGV^\^[qq^#e@9! !$% ]YE     ]Y]Y?+?+9/_^]^]]]+993333310"3 54&+53 54%2# (V98u и^[9$g((J?@ ^Y ]Y ?+?9/3+3933333210333##"'53265#^@ECNIC`UWo%2U@-4%0 )  34 aY-]Y &]Y #]Y#?+?+?+?+999333333310326=7##"323&=32&#"#"'26=4&#"Šoy F?/;cV+) 2u@wF%+q=^Jq^=@ ^Y aY aY?+?+9/+933310%#"!2&# 327#5!xj#{Bi9+"#+JH`-J$G@#&   %& " "]Y?+?399999333332310%#"&546733>34&'326mQ4gj9L`<*  $+B)#$(--EooOv.!^n22:<2;42^ 1K@&-3  23 ##/]Y*]Y?+?3+3999993332310%4'326#"&5467&#"563236?>32&#"RLL--ll8S&.%.:4G'. !D'I2;-%."XgkR1+)kg~~iHo5 )7I!32#4&#"#CB/;/2 1qʲw6AZ@PZ5L(D@$((")* aY ]Y %aY ?+?+?+?993333104&#"#32&#"3>32#"'53265wCB/;/2 1qCB*@/26AZ@PZh6A X@1  cY`  ^Yx ??9/]]3+3_^]]+933333103###5334632#"&b=-*??*-=)<66<;88JJFJ 9@   nY nY?+3?+393333310)57'5!Fj#-%kk%# T@1   ???9/]3/]339999933310"'#&#"#>32332673#+11i sb#+01f u b;3 3>32#"'5325#ߙmt /jN 5tCB*A`ÂJPZX`hwL^<@    ]Y]Y?+?+??999333210!"'5326533>32#4&#"b]2/;H7 3oIJw!YlݖQY55^ >@"  !"]Y ]Y ?+?+??9993333103267#"&54&#"#33>32L5H?O+w 3oēj[TJQY`J,@   ?3?39999333310##3.5`8 JsoJ'{qh^|q^#{@F $%  ]YE]Y]Y !]Y ]Y?+?+?+?+9/_^]^]]]+99933333310)5#"&5325!!!!!32654&#"/ŕ| 'o +qӕs^%B@!   &'# ##]Y#  ]Y?3+3?+9/99333104#"326533267#"'##"5! vi_fe]hzϸE AgKBh| 󀊬5Xo\JUNJ ?5(@  bY?+??9993310"'732>53#'#I8A6WU> `gkrJ7@  bY]Y?+?+?9933310327# 5467##"'732>533AL)/n >dI8A6WUlY!Vkr `gJ/^*@   bY?+??99933102&#"#33>I8=:WT?^ `g6mp/^3@ bY]Y?+?+?99331033>32&#"327#"&5?eI8=:WTHT=@DRJmp `g#da!^@ aY?+?9931034632.#"R^N8HG!Zc%^@ aY ?+?993104&#"'632jGH8N^RcZ! XJ A@   ]Y ]Y?+?39/+3993333310!#!2#4&#!! m΂~9vt LJx 3U[XJGoJ@ ?55hy^/M@'# )01,)!&]Y!^Y ]Y?+?+?+999933333310#"'327#"&532654&'.54632&#"y^FHS=@DQ|w~;=ptd>/ da!kXXJAZ:H7!Yl\V!YkLZ@/  ^Y]Y ]Y?+?+9/_^]_]3+393333323103#!"'53265#53!2.#"b]2/;H7\4>H7n!Yl<V!YkL^(@ ]Y]Y?+?+9323104&#"56323267# 87../V}}6I>4\dS!PlY!VL!P@+#  "# ]Y]Y  ]Y?+?_^]3+3?+99333233103!2.#"3##"&5463267#"\4>H7B5ZV!Yk9k{Upcb-Zf@?    dY/?O]YO_0?]q]q+9/_^]+3399333310"5>3 3#5!5!4&OKi0BHj>ZVH{\i!F@@  @  dY]Y?+?+339933331027# #5?3!!`9f5Hk=[ TVVH_fJh@6    ! ^Y  ]Y?+??39/_^]_]33+3399933333333310!33##'##"&=#53267!X7 1wɎwJNNOVы7=JF@$     !  ]Y]Y?+?3+399933333310#".5467!5!32654'5!mjoh뚘P2-H^/@ aY]Y?+?+?933104&#"5632#"&33265=P:;F;ߴlQoJ @     ??393310 #&'##qF)J\`{LJ3J"@  ?33?3999103673#.'## '##-("-- ,} &1JeiiJi(W&AJ+@    ]Y ?+?393993210!#&'##>32&#"HDCW?5D^t"9fhjϲ fXJ"@  ??39932310!#3 3Bsw{P\JG@& dYdY ]Y?+?+9?+9933310)5!5!!3267#"&5NT5HCN+}wGj[ PNBJ]@4   dY   dY   dY?3+39?+9_^]+933310!'7!5!5!3>32!"3254&),1NYviO7e6,ogxvtS[| uddBoZ:FZr6,fj90>K3-@   ]Y ?+?9/3933103>54#"'632G?CǺ66.s̻Ww5OGh@3-@  ]Y?+?9/393310#"'73254&'ОC>FɴmVr.69q^(@  aYaY?+?+993310"!2&#"327fP37br!4@;}&2y@?!o!!!! %+5]5XJ\\^"e@9   #$]YE]Y ]Y?+?+9/_^]^]]]+993333310 !3# !2654&' !"&54675&54697:V)uǚЗحg%9q%M@)' !!#&'$#^Y$$ aY aY aY?+?+?+9/+93333310%#"!254632&#"&# 327#5!xj#lVn~;?/;`Bi9+"#+bH`-jJ=#]@5 $%!cY` ]Y ]Y?+?_^]3+3?_^]]+9333231033##"&546;267#"4632#"&zXh9-Ny=-*??*-=JmzVocb<66<;88J6@     ???3939333310# 373#7O4$|} i8ulNVJ@]Y?+?993103!!XJLq',J@'.* #  -. ]Y']Y ]Y?+?+?+?9999333310!2&#"#467##"323.526=4&#"m/,ID1  vw  ǤV![iMw*  .y#!3R@+]Y  ]Y?+?9/39/_^]3+393333310!#53>54#"'6323#G?C߿P86.s̻W5PR@+ ]Y ]Y?+?9/39/_^]3+39333331035&54632.#"3###ݯӜD>FţYs.67Pq^%(g@8# '' ()*'dY&&dY   ]Y]Y?+?+?99?+9?+9933333310"323.53!!!'#'26=4&#"3w  TNsƤ{L( .y6ȋ!=Eq-:@F- 8(1+%1;<%"^Y-++]Y+)"5]Y".]Y ]Y?+?+?+???+99/+3999333333333310#"'532654&+5!#'##"323.53!26=4&#" ̢ysw  ɐ|HV}N( .y6!qN-%25>@R950 )#44%5<<5 )?@ 6dY 49 dY%3##3dY#!-]Y&]Y?+?+?99?+9?+9_^]+93333333310%3>32!#'67!'##"323.53!26=4&#""3254& Wwi(!9sw  {L8e6,}XT^9P)( .y6!=EZam1!F/a@2 ,,*!!*(01 @$!(]Y + +dY /]Y?+?+33?+99933333310#! #5?3!632&#"2654&'.547!3Hk%TX>otdN{t~;!`L/TjVHJFG>H7U>[!Yl SVHV!Yk+_f!F/:@O+%%#3 88 #%;<3 0# 0]Y  ((.aY(dY5  ]Y ?3+3?+333/?+9/_^]]+9999933333333310>32# '# #5?3!!3267&532&# "32654&_]ǡycHk=RCKm- T28bk>eRWiQ!OKF;sZISVHXm;Rp+"40G{M<09?1g@7%'/23'+!]Y+ ]Y+%%dY%]Y?+?+33?+?+?399333333310"'53254&#"#!##5754632&#"!3>32W;>=v}il0]F[X 6jȏkBT>?%xGVT&J@&  '(# ]Y ^Y?+?+??9993333310#"'#33 54&'.54632&#"ꬴ@w~;=ptd>/VBlAZ:32Ϣti&LR<032#4#"#2H;+3(Hti=G<(9FR!\ 5@ @Po V?]2/]393332107"'5326534632#"&TIDI22*<+,65-+3;>>/]~ 0o lE@gU1y?!@    V TU?2??9993310"'732653#';>B*]~ 0ty leW1!8@    @ P  VU?3?/]399333103267#"547#"'732653?'?/]:kM;>B*]~+B? !ABhT l J@)       /  V T?3]?39/]]]339933333103#!334+326Z\yRG{Xv@{@'"@ VT?3?3399910&'#3673?3D uv^Ff@3@II_7Y1g'RT!\/@  :  @ P  V?2/]9]39310373#"'532?$66nQ4I(q3&-_EZwdN NP + J -@ / /O_/]q33/]2102#52654&#+hxzf2A;8Juderf;66:+ J -@ / /O_/]q22/]310"&5463"3 fzxh2A;8teavg:66;'!*@ @H /29/+3933105654&#"'632RH/l*-n8;J"jDoMk!8!GH@3RI/10%5% ~R3P3RI/10-53~P3'^?/103# '3P^_@/10#33P@+}!v!C+_}H H++]5ydM@ p]5^^!J!@??99//]]10 !lJ!-J@ ?9/]10 J+ \+ \VV-7/210!!R{\7 @  _/]22/310327#"'9">/QT%p}KZ%zUK7N3#Z >@%  !" @P@P V?3/]q399933310#"&54673>34&'326.4oXXn.4½! ż  X?VspY=_7R=)T--T&'P@ T??9310#3Pjy!&@  "#WU?3?399333310#"'53254&'.54632&#"ᵩnxMo_/;eJKBpsw9Nh*;)0@Q;jy=:,&%428s+d 4@     V T?3?39993333310 33 # #`7/hX+D"@  T??39933310.54632.#"dB8z1Exa'-g*@ /3/99310!#!5!o @  //9/3993310!#!5!3oR$@ //9/]3993310!#!5!3o^ @  //9/3993310!#!5!3oV@ //399310)5!3@ //3993103!!$@ //9/]39933103!!#odiL  H H #?++]5N\@@H@H@ H+++55 H/+3?910#3dۢ%9H/+?29103# #d%=hj/@@H/+]?10%5% jNdۍhj/@@H/+]?1075-hN/d܎D /]10#.'53wCh-D476>? /33/]310673#%>73#S\!ByP&h FyZj;30G68?  /33/]310#.'53#.'53yA &c&y?#j!?39P.06M(}@     /]3210".#"#>3232673(OLG-2fqZ)QME,-h n#+#5>|#)#3>|hs@ `/22/]10!##Tmsmhs@ `/33/]10#5#5hmsmh; /22/1033mTmh; /33/10!5353hmm)V@  /]33/]310!3!53nsuVR)V /210!3!nsVR) /33310 5!!+Rdy{[!K2jMV+@@H@ H/++]210!!VV?NjO  jwc Po!S[!LR`?]10#RO @ `?3]210#!#ROO= %@ /_/]]22/]3210"&'3326734632#"& nTtda p =-08:.-=يF<>Du<7>56=8= #@/  _  /]]33/]2102#.#"#> n Uqg`p 슉I8@Ad ?10'63 4|B%f ?10#67 4|B%d ?10#'73%B|4 f ?10#67 4|B%3^ @ ` /]]10#.'53yK%v3^<89<3^ @ `   /]]10>73#5m!,?wwD?@1LB H/+9/310353#5#ᇇᾅ{LB H/+9/310##33ᇇDžmj@ _/]210!#!ڈjg-q /33/10>53ps"3s  /33/]210"&5463"3sgyxh2A;83vcavf;66:)V@ /]3/]33103!535DRb{{)V@ /]333/]105#5!#DV{{)- -@      /q33322/]/]q]1053533##5ד{{2eM@ p]5V kY/+/10"'53253><.8bk7jV kY//+10"3327b8.<-k ej@/  ? P  ]q55 0PW 2H ?+55~;99zY=Q6`RH H++]5Bm//]2/310!#5!#ڈ6b}& @ H /]3/+33310#"'#"&53326533265wjo55ohwop3@bs3@}q|GGzsBEBEi[L  H H #?++]5g[K  H H #?++]5?N H+]q5= H+]q5xR@ / H+q52eM@ p]55H/310!5!jŃY9]N@   /33/]210".#"#>3232673&HEA,* h eU(KE?**g d%+%;w++/10 L9}j ?/10 #py3s   /22/]3102#52654&#mhxxh2A;8udbug:66;Bm@ o/33/]310!3!53m&ʈB\5-@  0/33/]310!!35#fٴ-}$ @ H /]333+22104632632#4#"#4#"}wjo56nhwnq3@bs3?q|HHzsBEBE/3 "@o   / O _  /]q1077''7V{yX{{Xy{VyX{{Xy{VyyV{}@O_/]10463"#52654.r<;%+%t<;%+%FK]g.5>G(L^h,8>EW[@/?o]55S!C4K!v,xR~n93?5>xU@ @H+555=B@ `p/33/]210!#5!#B|W9[ `H H++]55B@ _/]22/]10!#5#|{w-<@$ / /]]2/]3//999910"''7&#"#>327326739[L\J-11i sa:LE\C0$01g v/}8x;32326734632#"&4632#"&+SOI"11i sa-UNH 01g q8(.2:&(88&.2:&&8%+%;3232673".#"#>3232673'MIF&*h hU*PIC+&f eW'MIF&*h dY*PIC+&f f$,8pz%6/pz$,8k~$6.n{?f  /33310%35 5#F /]9/3105#7#Bxx% !'/7AIS]gqy@w  &$622?2O2_2?O[ooVjv~~rzB88F< QeeL` .*0*@**$2jz<`**`j=-08:.-=n n Uqbd p L<6=56=8I8=D=7  /1077''7VidaegVidaeVfd`diVgeadT @ 0O_/]]10&'5673_x,uHmghG:,gT @ 0O _  /]]10#567&'5g4V)iSRj K.iH34f#@   0O_/]]2910>73#&'##567&'5 YRh,:,!hd/_'nO39CT2=@@% HO/O_ /]q333/]/+q10#7#73Fi%Fi%T) @ P`/22/]310 $'3!2$73qgUJOar)ƻztT3;@/_]5Bh@/_/]310!5!4בBi=P+5T-@ /`    /]]r33/]21023273#".#"#svhuuh.&/&}&/&}T3 /@"P` ? O o  / _   /]q33/]210 #&!"#6$b/UOa3ƻztT?/22310!5 5!+)%#&@ ) 9  X[Y?3?3?9/q3910'#"&54%754&#"'632%26=5fBoyV`?92g0+wRdQlc<5eA0na K<$h?ny3cZV/:?0.)3/@ ;/@ H[ Y?2?39/]+q]q310"&54632!3267"!.%14dQ8nfDQ 4G)ŨN!}RWMJZ5R@ ZX??]210#3'4632#"&H1# 00 #15+''+((()J  [Y?3?310#"&5463232654&#"J]WX\po)/@ Z XY?3??391032653#'#"&5^Y} &k<NlubVc2=w)  [Y?2?310"&54632&#"327=lX)i4XVYjN)+q#pw/{+)=(@/  @H X[Y?2?3?+q9910"&54632&53#''26=4&#"uOz $f.aOU]RP)e <Ce3>sknqo5/@  @H X[?3?3+9104#"#3>32^Y#o95iz*68wG 5"@ZX [?333?33?99104#"#4#"#3>32>32fvZLyTO} )_9=#vBzz5idkxd?2y<=xG)5@ Z X[?2??9102&#"#3>w)9AKj'Z t]TH)/@ Z XY?3??391032653#'#"&5^Y} &k<NlubVc2=w5X ZX?2?3103673N 5sWA\<V5T @  Z X?3?39910 373#'#T򤤢N)o@  `?]9910673#)VD;8we*)=@  `/]]9910#5673,XywC;f=Df^Cq^&FOb!@0!P!!!!!!%+5]q5Df^&COd$@0!P!!!!!!%+5]q5?ffJ(3`@5+&&1 145#aY .]Y  )]Y ]Y ?+?+9/_^]+_^]+93333310>32#"4632#"2654&#""32654&R/3}v~^ft1 £_+E[fdsGYo~zyuȋ}T{D}RF $.?3;D'TQ@ &%+5?5)&QjR@ +&( %+55+55o\^)\@0  " ( *+ ]Y%]YaY?+?+?+??99933333333210"'532=$47#654&#"'63 3327/D@3+9VT5qD^!<@!  "# ]YaY?+/+999933331032654&'.5!2&#"#"'sX\gnUe>zɪrNPB7: PNû} V@1    iYI  ? _ o    iY?+?9/_^]]+9/99333310#!#!!}XjJ X@2    /    ]Y?O ]Y?+?9/_^]+9/_^]99333310#!!!#!d6RD)#E@$ !!$%iY kY kY?+?+9/+9333333210!654&#"'632!327#"&547v4*0$/CP%9{5-9.(@C'1*.qf>eweI"<=~8uOBq\S3H@&     iY?+?9/9/993333210!4''&''&#"'>3 }{O5Rl\?V[~D\y/!R;V J64D9,SfQ@-   / ??39/]]9/9993333210%4''%&''%&$/#-*M+/wȫ:L VL](?~[fu.G@$'# /0 ! iY '(iY'#?+?3+3?339993333310%##"&'##"&533265332653#!5!26546 3w- :~vw zWedhbj tc䢓~*B)J,O@($ ) ,,) -. $%]Y$  ]Y ?3+3?33/+99//93333310%# '##"&533265332653#!5!26=472hN 5tߘntFSWX`=^=:BFs@@   iY iY?+??9/+9993333310&#"32653#47##"5432;cnͺ =؂x/J/`\k1q?`<@   !  ]Y]Y?+?+??99333310"32653#47##"32&!y} 2qY#/1ո8TFQY(& 9@ iYiY???+9/+99333310!#3>32!"&'53 #"G]UF{w^L>=g1s6E #J7@ aY aY ?+??9/+99333310>32#"'532654&#"#3b<~Sljn~d}.2<=b#J`-T@+# ++ #./'#+  iY  iY ?+?+9/_^]9993333310".546323267#"$54>7>54&H{{ϟ>acR}7)crL@mBɬK:R^Cn~<9dcr?4M_Ggn1^*V@-*((""+, " %]Y]Y?+?+9/_^]9993333310&54632327#"$54>7>54&#"=ڻۼƄ?YYʋswfps+bU;cmQ^.-nZ32&#"! !)U/0##!/D?X~G8JZ<@D0!"2B.1'qCcoY.E]dDo!!3^"G@&  " #$ ]Y  dY ?+99?3+3999333107! &#"!5'.#"'>327>32dw.7"_d$2% -1+F`)^\&`G8CZ (2{{f3# =:9<}!R@* "# iY iY iY ?+?+9/_^]+9399333310"3>3 ! ! & !"/6Tۘ'LoC'JB)XNdZuVPb˶qb^#?@   $%]Y ]Y]Y?+?+9/+99333310"!2.# 32654!"5>32m0ı6ILL3-i~&;;!Pӌv.(#/xj)J C@"  !" kY ???3+39/3933333102#>54&+##"#&546;3)3 >324&#"7>267! pv7Gg,6o X^Qj Wąa^Hv ~E{uT(6S]U] o ,%"gV\bjס5J#p@<   $% dY 5 #^Y^Y?+?+9/_^]^]]33+33933333333310#53!23##!3254#'32654&+PVծThyhvLJlBGrKUPEyX&@ ]Y ]Y ?+?+9310"327#"32&rJ\&E1'-HBJJ(@   ^Y^Y?+?+993310)! 4&+3 Ji#ž/JJJJ ~@R ]Y8i/o?O  ^Y ^Y?+?+9/_^]qr]]q3+393333310)#53! 4&+!!3 Jrr] &“t/ՓBJ Q@.   ^Y ]Y ]Y?+?+9/_^]^]]+933310)!!!!!Bn$AJϑV{X$c@:  %&^YXho ""dY"dY?+?+9/_^]q]]+99333310#"'532654!#532654&#"'632dudχOP²k\LaTBe4ΜA%/d\aSHR(=u{dJ'@  cY??]+93103##"&54632=-*??*-=J<77<;88^J "@  ]Y?/]+93210"'53253+FAF=6ՙ J 6@    ?3?3939333310!##3673 X* {?LXJ 5#+FJ L@,    @  ]Y?+?9/_^]993333103'737!=HJ`#wNH q{͖#J0@     ?33?3999333310!#33#47CBRZjJVNBJ,@   ?3?39999333310!##3&53B DWF;J iHkyZ (@  ]Y ^Y?+?+993310#"3232654&#"')  'HX&@  ]Y]Y?+?+9310"'732654&#"5>32ЎCprDaGB23)! &@ bY bY/+/+993310% 546$3 "3265oЊ -)~=?3+@   bY/+/993333104! '654&#"#&3#, 3?<O:8et%"Q@-   #$ bY bY /+/+99933333310% 547'76! '"6527qDsP -JsN`s3af/%sRw\vOyZ=1>Gm?}/Ekj#\+2t@C&0& /340^Y /?#]YaY),,]Y ?3+3?3++9/_^]^]+99933333310 >32#"&'#"=!!"5>4&#"326267!!?Јz>< \cPے| \psqpns m} ,%#ԟuJ#L@'  $% ""^Y^Y?+?39/+9993333331026=3#"&547&=3!2654! 3gnHSϘm~qhd+SݰΪRTƔgrzmy'Z @   ]Y ?+299104&#"#32۪' 'y' @   ^Y?+29910#"33265ᆲ') J :@  ^Y^Y?+?9/_^]+9933310+#! 32654&+i9X|w`J`i`^1J G@$   ^Y  ^Y ?+?39/_^]+9993333310 #.5463!##";9shHz~F*pQ]1JG@$ ^Y  ^Y ?+?39/_^]+9993333310#";3!"&54673Ӌ~zhs\Rp*E+J%@ ]Y?+3?9310!#!5!!7`J%@  ^Y?+?3993310#"&533265綂J==}~N`6@  bY  bY /+3/+993333310!2654&#!5!#!NJQY5w 3oN` ,j@8  $$**-. !'' bY   bY /+3/_^]+99//3_^]393333333310!2654&#!5!#!2#"&5462#"&546JRX56//642246//6422y 4m8('::'(88&'::'&8NB"v@D" "#$ bY "bY" "bY/?o /]]q+/_^]+9/+939933333333310!2654&#!5! 54&#!5!#!N‚JPZX`53lsᙌ /iN 4tJ @    ??2999103673## kJGdFVY)J"@   ?3?3399910!#&'#3673673Ӯվ ŰU4-`=Jh@YKVlG]@`VyJ 8@ ]Y]Y?+9?+993310)5!5!!y3By;yDJK@'  ^Y dY ]Y ?+?+99/+39333310!5!#"'532654&+5j 򄷽!ƟGVgdfZdFX#=@ $% ]Y!^Y!?+?+99993333104>7>54&#"'6323267#"&d?Z]]b7̅grqDV-JnW30RF?OBDu;8W@KS,&A!Z!.@  "# ]Y?3+3?99310327#"&'#"'53267.54632D,7?2U[X\YS6J9{J|sȢB\evsvs]ddHJ@]Y?+?99310!#HJLJJ @   ?3?99910!#&'#3$  j@TZLJJ%@ ]Y?+?3993310!#!#!bJJJmJ@@    ^Y ??339/+3393333310!##".53!3 3+ ij˔Dezquq|eJ)@ ]Y dY?+?+?99310!#! #"'532>7!2Gvi>=@**30IlwQ)@ 0IN?3?9/]39910!#3 &'%{ym  j114E S@/       N IN?3?33?9/39/]]q39333310!!#!!!!!!#pu012 O@   @I I N?3?29/]]+3993333310!2#!32654&+3254#5TPůpamw~Rr9RFPJ?`#c@   $%  @I#IN?3?39/]]+33333933333333310#53!23##!3254#'32654&+5PơMů箦pamw~aADhFPJ? @   IN?3?3993310)!24&+3 Luイ >@#  I N?3?39/]]q3933310!!!!!!^Jco <@"    I N?3?39/]]q3933310!!5!!5!!odJ`=Fq.@  JO?3?39/3933310!#"5432&#"327#\%;Eo5AAʹ >@"   IN?3?39/]]q399333310#!#3!3Ө!ߨ3\T 0@   I N?33?3393333310!57'5!kwwxx```D !@ @` I?]293210"'532653'=@G4<=JF% 8@     IN?3?3999333310##3>3R#k`Hy/+B@ IN?2?993103!0@    I N?33?3999333310 #3 3#47h+1\AmQF ,@    IN?3?39999333310##3&53blZo= ,@    I N?3?2999933331033#47#ӅT'EqB  @  JO?3?3993310#"543232654&#"Bߡm$A@ ! !!%& ##IO?3?39/39993333331026=3#"&547.=33254#"_hBNZiùEFfZj_](#jM&XahT 0@  NI?3?9/]39933310+#! 32654&+T`!Rr|n{VeXX8@    N I?3?39/3999333331032654&+#!2#Lpgnq}-ǼWWYK)hL='H @ NI?33?9310#!5!! !o @ I O?3?3993310#"&533265ըt~sȳs}u%^"@   IN?3?3399910#&'#3673?3Hؠ겞  R-&,"lTB^6bJ(Z#A@#! $%   NLO?3?3?9/]q399333310'#"&54%754&#"'632%26=j.q[{oIC7t61`m\yoBV4.zm VB)uH}qi^3BG62#=@ !!$% / KOL?3??9/]]399933310>323267#"&5"7>54&3sTzoIB8r81s`mZzpBT7+|m UB(wG|oj^4AG64h30@    K NLO?2?3??99933310"&5463273#''26=4&#"`)l326324&#"7>27!l]38HH&uJEvAAvI`+`y>3YeVpi}L !At *w8?X  RJxp65j]3AVb^0@   F NLO?3?2??9999333102#"'#3>"324&T}/f6f]_hZͿsg5U<;:vxh34@     FNLO?2?3??999333310"&54632&53#''2=4&#"Ni) 6k0`hVa\л=8MHi@55}hB@&   / LO?2?39/]]]]q39933310"&54632!3267"!.qgE{HuN\ [OзݿXpu 3aXTeb:@     ,   LO?3?29/]q3993333102#"&=!.#"5627!¢rgtpWиۼVqt=6bX`X ]@9 !"       /   L O?3?39/]]]]]]qq399333310#"327#"&547.54632&#"39{¶ulBUIQ>tkqnH7zi1W?ar%{8[bH]@9  ! /  LO?3?39/]]]]]]qq399333310254#"'632#"'53254+5;ǚ;g?9l{b[{qGJP%50=@ KN L?333?33?9993333104#"#4#"#3>32632\eU^Y .lAAVxpZxrrG8h=2@KN LM?2?3??9933310"'53254#"#3632^9@A(Lkb blhgNwpjwmhP  @  LO?3?3993310#"&54632324&#"PǰŰchcjef7պֶ}F @  LO?3?3993310632#"'732#"VV}c1*c%bs0ӿ/ 5h5P @   L?3299104&#"#4632he˨Ư5ضhP5 @   O?329910323#"&5ͨƱ5Թh^0@    K MLO?3?2??9999333102#"&'#3>"32654&Mj(1n2`i[]]ξ=8HNNh=8~~1#`.@    KO?3?399333310267#"&5#5?33#MT&|umq3m6%z zxN3{c>;5)@    K NO?3??39993331032653#'#"&51HLka -yDTPzq9DXf*@    /33/399333310!2654&#!5!#!XSPyoq9D HKkb -yD9@  !KN O?333??339993333103265332653#'#"'#"&5/dW_Y .lAC)KwpwqG6DC @  KN?2?39910 3673=կ@>n]O!(@"#L O?333?99310327#".'#"'532>7&54632uYMJT2,$E;HI'9nOF%1)&.5utECd w80B?y,$sh$?@" ""%& MG O?3?2?9/399333333102#"'#46"3254&+532654&sjhixk^P\fc򒅷2/ꔝ5>3bcXTNNh@   KM??399910#4673673'!Ŭ-&!%h:`qrFHlVfN)8@ $*+! F'O?3?393393333310467.54632&#"#"&%4&'326fSK~K^Hq50Coǰ@VLx|mZdkt,3hEbl#,}M-"*D:QrXn&eYirhh <@  !"LML O?333?3??933333310.54746324&#">״9B˄rЯJ9Tdsh@ϯϽVF^"ҫ}qhH /@!"KMK M?3?2??999331023327#"&/#.#"56-<.%P˰0$$0/>Yj,TLs)"/:ZtG0 yRq`F!37y`By,@  RP??]2933310#3'4632#"&76($77$(61--1---`yo%@  R PS?2??99933102&#"#3>2?31Vu/co efcKU5c P?5ac P?5  Q?55cR?5No8@  0    SQ?3?3]q99333310%#"'#4632%"32654&NnS`[HpeZY/8dսS;hr Q?55HeR?5^%,g@8# ** -.)^Y)))) &]YaY^Y?+?+?+?39/_^]_]+999333310"&'#"&5332653632!3267"!.oH4約}uXmX /^j_c=}sm-&!ߦ{,9@K 77*:;$!&)// @&/ ""-]Y4]Y?+?+??999/_^]3^]q]232999993333210"'3632#"&'##&#"#>325332673"32654& oo7!++ i eU)+f f qqPOx ;32533267326=4&#"hsw  #++ i eU*+f fX( .y;32#5754632&#"!!32673 ++ h dUil0]F[X**f h L;?%xG;<~^+4=@V'?5  ,7#++. >? 7,#.&55/555@*.@   1;;]Y?3+3?33?9/_^]333]2299933333333332310!"%#$'##>733>3 3>32>735#"%54&#"#-/i`] /jN 5t2+ g aaFBߙICmt+B* .2`xǖPZX`Ӟ 5,azZP):-[^ +~@H- ! %,-?!!!!@ H! !%%@ )]Y?+?3?99/_^]333/+]q33339933333332310!&'&'##>733>32>7354&#"a]Z ic\ 3o0.g]`w)) cpxQYϦ:5&d &+ {^,9@, 1$ 77*:;$&)/ @& @ H -]Y4]Y?+?+??999/+33_^]]22999993333210"'#5&#"#>3233>32#"'#32673"32654&#++ i eU @nw *+f f ;3233>32&#"32673++ i eU $?eI8=:WT*+f fj  ;3254632.#"32673#"' ++ i eUR^N8HG!*+f fT;3#5?3!!32673#[Q#^i6,* h eU"Hk=$**g dr_f S;32!5!32673AeT0-++ h dUCo*&**g d)w;323##"'###267!"!.@nb\ w VZP)N==ȵɴFJc@5     ^Y5^Y?+?39/_^]^]]33+339933333333103##"&=#533!26=!璒JCwsC9~ww}J!*|@G(!'((&+,'^Y5 ]Y "]Y ?+?+99/_^]^]]33+33933333333103##".=#5367!5!!.'5!26=!/o[]o)L|[zJӚ}z y"slͿ j{ -P@,++./ !]Y (]Y aY#?+?+?+??99333310"'532=#"&'##33632"32654&.8cmil0]F[X[jkT>?%xGo ^)6l@:#4-) )78  ^Y 1]Y *]YaY#!&]Y!?+?+?+?+?9/+9993333333310%7##"32373!#"'532=!#"'53265%26=4&#"oy 3 3>323?;?.8bjߙmt /jN 5tZjkÂJPZX`j^ N@)   !"  ]Y ]Y aY#?+?+?+??993333310"'532=#4&#"#33>32332#"'532="32654&w @nI8=:WTZ/TkEXXJAZ:H7k!Yl\V!YkjJ?@    ^YaY#?+?+?399333231033>73!#"'532=!E D.8b1bekJPjsJE@%  dY  dY aY#?+?+9?+9933310#"'532=!5!5!!s32332726=wus;#R|lwWD7S`Z65.0*ijgINA}w4 ,2H;cjrV\qj`^*W@.,( ! +, %]Y ]Y]Y]Y#?+?+?+?+?99933333310"323733327#"5#'#'26=4&#"3w[551-*YJsƤ( .LH;!q 5W@.++7 /%33/674 !aY]Y ]Y -(]Y-?+?+?+?+999333333310%26=4&#""323.=32&#"327#"5467#Psw  H?/;/2-8@&*e  v!ҕ*  .y6AapU!Vwqj^%Y@1'  ##&'" ^Y""""]YaY]Y#?+?+?+9/_^]_]+9333310"32!3267327#"5"!.Xj651-*YZ/+9m-H;ߦXj\^0z@D2( .." "1200]YE0000000%%,]Y%]Y]Y#?+?+?+9/_^]^]]]+993333333310# 3267327#"5#"&54675.54632.#"!וʔUd651-*YZsqcjoWDcJ9Y]'/H;c& ]%),Dj^.w@C#-# ))#/0-..-]YE....... ]Y &]Y!]Y!#?+?+?+9/_^]^]]]+99333333310 54#"'632#"'327#"32654&+57O_?}vu`651-*Y緽(L8$g}H;VV^\^[hju^!(o@B *&%)*&&^Y /?OaY"]Y ]Y #?+?+?+9/_^]q^]3+39333331023327#"#"=!.#"5>267!65.0*YXj[^9H;5 m-' !jG@(  cY` ]Y ]Y #?+?+?_^]]+933310%3327#"5#34632#"&bZ651-*Ym=-*??*-=H;J)<66<;88Djf^"6@ ""#$aYaY ]Y #?+?+?+933310732654&#"'>32#"'327#"V7271^H*64/0*Z@"sH;jL :@" !"]Y^Y ]Y #?+?+?+93323310327#"3265!2.#"b~~651-*Y19H7\4>H7BmH;YlV!YkjfJ!I@&#   "#! ]Y]Y]Y#?+?+?+?3993333310326533327#"5#'##"&5Xw}Z641-*YL 1wJ="32654&\(l=h_`i[[[мuih8=t~~h @  LO?2?3993310"&54632&#"327ױ·6($77$(6nlrTLYS2?:1--1-..h @   FM?3?93310327#"&57X%P?F|ruwyzzh3 @   F M?3?93210#"'532653szF?N&/)szzy<;@ KN?3?993103!!Zh'D@"  ()  KN $ LM?3?333?3?9993333310#"'53254#"#4#"#3>326326:>/eU^Y .lAAV7AqxpZxrrG8h <@ !" KM O?333??339993333103265332653#47#"'#"&5/dW_Y .lACXwpw:E>G6h;2@    KNLM?3?3??999333210#"'532653>3 #4#"7B4< & &Rjc\{4CXt=Dyh4@  KNL M?3?3??9993333103267#"54#"#3632;);C"̖jc e^?8 { Byrp}L ,@    KN?3?39999333310##3&5Lh)9`f'_@3    / K NO?3??39/]]33333993333333310!33##'#"&=#53267!1`mm -yDdd:faH'}q9DQ}'qlGTPDs:@     ! KO?3?39933333310#"&5467#5!32654&'5!KQǰRJjIUhcbk]Em5-Y³q7t mozzqet9 @   K O?3?39933102653#"&53\WW'ixNRxi9%@ KLO?3?3?933104&#"5632#"&533265",43B;ufPbaRB.v|ͰRvkhy @    N K??399910 #&'#--WU\PAR .@ KN?39?3999333310!5!5!!4v`'{lRhH9@ KN M?3?39?3993333310!5!5!!3267#"&5D4v&A 4Ec^`'{lC4{x|R55e@;    /  K N?3339?399/]q3]]933333310'?#5!5!3>32#7"32654&6x4vREZMc8?8E5,1*$`'{l\XCb!-h:@ MK?39?39/3393333310#"'532654&+5!5!ٴp54.54>54#"'632Z!(!!(!#+#2,.C6h & $$ZN?  7=   q@   /]3]210"#"&=332>;dNwp:n|k*cxWT%-%nmu#+#7@/_/]210!7!%Ej/@/_/]310!%7!/E%ٚ7 /2310!'!JEߙ/ /3310!'%!/EJNB/@ fviy_/]2/]33]]10%7%'E(EÛB/@ fviy_/]3/]33]]10'%7E(EHZ  H/+2/102&#"#36d'%&JCyiABn Y[PZTR @ /?/]10&'5673_x-uHmgiG:,g#@  0O_/]]2910#.'537673%#567&'5 NRh*=*#hd/_'nO=[T2:&('N Rz{@ &% %+5+5+5q&H&Nzo@)/*%' %+5+57&)O\R@ & %+5+5`&IO{@  %&+5+5};&*MR@&w%+5+]5q=j&JM ,+%+5%7&+OR@ &  %+5+5L7&KOR@ 8 % &+5+5%&+dZ   %+5L&Kd %+5%)&+jR@ !&  %+55+55L+&KjdT@ 8) %,&+55+55Z%&+z= %+5>L&Kz! %& %+5%&+N"   @ H  %+5+]q5L&KN$ H" %+5+]q5&,R%@ @H@ H! %+5++q5&LR'@ @H H% %+5++q5)wJ&,JR&@ 0@&( %+555+q555D&@  %+555s&.vR@ &%+5+53&Nv{{@ k %&+5+5&.dδ %+53&NdѴ %+5&.Mq@  p  %+5]53&NM@  p %+5]5&/d %+5s&Odm  %+5&/'MRd)@  &@ % %+5+5+]5:&O'Mdm'@_o@H&%%+5+5++q5&/M@  p %+5]58&OM@ p%+5]5g&/K! H# %+5?+]5gc&OK@ H# %+5?+]5{7&0OR@ & %+5+5&PO#)"%+5{&0d %+5^&Pd!#)"%+5N7&1OR& %+5+5L&QO  %+5N&1do  %+5L^&Qd %+5N&1M@  p %+5]5L^&QM@  p %+5]5gN&1K!!@ H!#! %+5?+]5gL^&QK!"" H"#" %+5?+]5}^&2 HR"H&!-%+55++55qh &R Hj!-%+55}&2 FR$0@H0&9E%+555++555qh&R Fj9E%+555}^&2 IR)@P` @H&%+55++qr55qh &R Ij%+55}^&2 JR)@P` @H&%+55++qr55qh &R Jj%+55os&3vXR@ &%+5+5{!&Sv =+' %+5o7&3ObR&Ѵ%+5+5{&SO"( %+57&5OsR& %+5+5/&UO %+5&5d %+5/^&Udm  %+5&5'M!Rd+@& % %+5+5+]5/j&U&Mdm % %+5+5&5MJ@  pԴ %+5]5/^&UM@ p %+5]5h7&6O=R@ /&&,%+5+5hy&VO$*%+5h&6d&,%+5hy^&Vd9$*%+5hs&6 CVR@ ;&N&7%+55+55hy!&V C "$5%+55h&6 DFR@ <&>9%+55+55hy&V D  <7%+55h7&6'O=Rd/&@ 28%&,%+5+5+5hy&V'Od9@ 06%$*%+5+5\7&7O/R@ &%+5+5!&WO+@0 O   %+5q5\&7d %+5!F&Wd/  %+5\&7M@ p %+5]5!F&WM]@ p %+5]5g\&7K@ H#%+5?+]5!g F&WKQ!$$ H$# %+5?+]5&8j#@/?P$%+55]q55DJ&Xj&@/?P' %+55]q55&8Rs'@ /@ H'%+5+qq5DJ&XR)@ /!!!!! H!* %+5+qq5g&8K@ H#%+5?+]5gDJ&XK!"" H"#" %+5?+]5^&8 HR @H&'%+55++55D &X Hy * %+55&8 ER1@!P-`- ----@H-&-,%+555++]qr555D&X Ew@ 0/ %+5553&9RR@  & %+5+5&YR # %+5&9d  %+5J&Ydm  %+5V7&:OR@ "& %+5+53&ZO  & %+5V&:d  %+53J&Zd  & %+57&;ONR@ & %+5+5%&[O   %+5)&;jR!& %+55+55%&[j   %+557&<O9R& %+5+5&\O %+5NDs&=KR@ & %+5+5Ps!&]K  %+5ND&=d   %+5PsJ&]dF   %+5ND&=M@ p    %+5]5PsJ&]M@ p    %+5]5L&KM@  p %+5]5!&Wjߴ) %+553&ZP & %+55&\P  %+55^J&D ,)%+5`&AO{@ &  %+5+5d"L@( " #$"kY  iY kY?+?+?9/+393333310 .#"#4! #"'53265!#?&w&~lU\9POSŴNO.2 q1&~s  -3%+5q1&~Hߴ6-%+5q1&~5-%+55q1&~۴>-%+55q1&~ "-@%+55q1&~ 6@%+55q&~ 6B%+55q&~6B%+55&$v%+5?5&$Њt%+5?5'$%%+55?55'$"~%%+55?55'$!%%+55?55'$!%%+55?55|'$"@o##%+55]55|'$"@o##%+55]55X1&) 30,%+5X1& /,%+5X1& *8-%+55X1&  7-%+55X1& W09%+55X1& B/9%+55'(p %+5?5'(c %+5?5'(Ŵ #%+55?55'(  #%+55?55'( #%+55?55'(ݴ#%+55?55L1& 9 %+5L1&  %+5L1&'' %+55L1&B& %+55L1&7 9( %+55L1&% '( %+55L&B $* %+55L&B $* %+55'+p %+5?5'+c %+5?5'+Ŵ #%+55?55'+  #%+55?55'+ٴ #%+55?55'+Ҵ#%+55?55|'+"@ o   !!%+55]55|'+@ o    !!%+55]551& %+51&%+51& %+551& !%+5581& U#%+551& %#%+55& (-%+55&0(%+55R',p%+5?5E',c %+5?5d',#%+55?55Z',  #%+55?55',5ܴ #%+55?55',5մ#%+55?55|',=@ o   !!%+55]55|',=@ o   !!%+55]55qh1&Rh"%+5qh1&R\!%+5qh1&R*%+55qh1&R3)%+55qh1&R )"+%+55qh1&R !+%+558&2up%+5?5J'2c$д%+5?5}'2#%+55?55s'2,%+55?556'2st--%+55?556'2s$t--%+55?55y1&{%+5y1&d%+5y1&#'%+55y1&;&%+55y1& (%+55y1& (%+55y&3 *%+55y&*%+55'<5c %+5?5'<?~%+55?55'<T۴%+55?55|'<@ o   %+55]55s1& 2. %+5s1& 1. %+5s1&:/ %+55s1& 9/ %+55s1& )2; %+55s1& 1; %+55s& 1= %+55s& 1= %+55k&vup#&& %+5?5'vc, %+5?5'v+'' %+55?55'v4'' %+55?55s'v}#d55 %+55?55}'v,Z55 %+55?55g|'vq"@ o   == %+55]55g|'vq"@ o   88 %+55]55q&~0-%+5q&~ 41%+5X&)&%+5X& 6-*%+5L&+Ҵ %+5L&H D %+5D&Ӵ%+5& /%+5qh&R˴%+5qh&R% 2%+5y&%+5y&- %+5s&Ҵ,/ %+5s& -/, %+5q=1&~'s @ I<% -3%+5+5q=1&~'H I<%6-%+5+5q=1&~& QD%5-%+55+5q=1&~& QD%۴>-%+55+5q=1&~&  @ QD%"-@%+55+5q=1&~& @ QD%6@%+55+5q=&~& @ _R%6B%+55+5q=&~& ^Q%6B%+55+5&&$@ ,.%%+55+5?5&Њ&$ @ ,.% %+55+5?5''$! @ 4%6%%+55+5?55''$#4%6%%+55+5?55c''$!@ 4%6%%+55+5?55c''$! @ 4%6%%+55+5?55k|''$+@ o@ B3,D%@**%+55+5]55k|''$+@ o@ A2+C%@))%+55+5]55L1&'@1$ %@ %+5+5L1&'@1$ %  %+5+5L1&&'@9, % %+55+5L1&&B@ 9, %& %+55+5L1&&7@9, %@( %+55+5L1&&%@9, %'( %+55+5L&&B@G: %$* %+55+5L&&B@F9 %$* %+55+5 @'+'p@ *,%j%+5+5?5 3'+'c@ *,%g %+5+5?5 q'+'!@ 2#4%z %+55+5?55 g'+'!@  2#4%z %+55+5?55 R'+'!@ 2#4%%+55+5?55 R'+'!@ 2#4%%+55+5?55 y|'+'*@ o   @1B%!!%+55+5]55 e|'+''@ o   ?0A% !!%+55+5]55s=1&'@ D7%(. %+5+5s=1&'D7%1( %+5+5s=1&'@ L?%0( %+55+5s=1&'L?%9( %+55+5s=1&'@ L?%0(; %+55+5s=1&'@ L?%1; %+55+5s=&'ZM%1= %+55+5s=&'YL%1= %+55+5 V&vu'p#ߵ=0@%&& %+5+5?5 s'v'c,ߵ>/@% %+5+5?5 'v'#+F7H%'' %+55+5?55 'v'#4F7H% %+55+5?55 ^'v}'##߶F7H%d55 %+55+5?55 i'v'!,@ F7H%%33 %+55+5?55 R|'vq'-@  o   ߶TEV%== %+55+5]55 R|'vq'-@  o   ߶SDU%88 %+55+5]55q&~N08%+5qj&~M-.%+5q=&~& B5%0-%+5+5q=^&~ :-%+5q=&~& @ B5%41%+5+5q&~R6B%+5q=&~&R RE%6B%+5+5>&$N/R@ %&+5+5&$MBR@%&+]5+5&$%+5?5&$Y(%+5?5&$%+5s1:@   0@ "H _  /]+]q293104632565"&=-27jxy-=4.D5mz K U.= -@  `Y `    /]/]+93310327#"&=$,6GJXo-) w^eYs?5R#/]@;*$$ 01  @ H  /@H'-! !!!/]q]3333/+]q2/+]3393310".#"#>32326734632#"&%4632#"&+SNI"21^ ja-UNG /2\ m8('::'(88&'::'&8$6.l}$6.qx6..651156..6511L&&+* %Ѵ %+5+5L^& " %+5L&&H@* %D %+5+5L&R * %+5L&&R@:- %* %+5+5'(:y%+5?5'(%+5?5'+:y %+5?5'+%+5?5&+  %+5?b14@ o_/]]]29310#&'53%4632565"&bVED=-27jxy-=٥j4.D5mz K U.h14@    o_/]]]293104632565"&673#w=-27jxy-=DP{V4.D5mz K U.j$F@.## %&  @ H   / _   /]2/+]339310".#"#>32326734632565"+SNI"21^ ja-UNG /2\ m64iqqyj$6.l}$6.qxs*.j]] D6&N %+5j&M %+59&@ *%+5559&@ *%+555&R %%+5&@ %%+555>&,NR@  & %+5+5,&,MR@& %+5+]5/',:s%+5?5T',%+5?5+D14@  o_/]]]29310#&'53%#.54632DVC>>-ywj71->٩2.U K zm5D.h14@   o_/]]]29310#.54632673#;=-yxj72-=:DP{V2.U K zm5D.j#F@.  $%  @ H  "/_/]2/+]339310".#"#>3232673#.5432+SNI"21^ ja-UNG /2\ mjyrohj$6.l}$6.qxsV6D ^\jy&N+ %+5yj&M-%+5y9&%/%+555y9&%/%+555f1& '# %+5f1&\&# %+5y&R*%+5y&*%+555>&<NR@  & %+5+5&<MR@  & %+5+]5'<):i%+5?5'<% ɴ %+5?5'3c]%+5?59;@!   ! o /]q]]22393310#.'53%4632#"&%432#"&V?q@H6(&88&(6_%92,*5N7{@6./55225d/5-:29;@!   ! o /]q]]22393310673#'4632#"&%432#"&:#q=V6(&88&(6_%92,*5 ;KX6./55225d/5-:2$@ o_/]]]9910#&'53VCD٩js=&'=0%Ѵ+( %+5+5s=J&5(%+5s=&'@ =0%-/, %+5+5s&R 1= %+5s=&'RM@%1= %+5+5R'2:%+5?5&2D@ -%+5?5'v:%ܴ %+5?5:&vD@ "'$$ %+5?5N&vB/ 1%+5 $@ o_/]]]9910673#>CV1:@   0   @ "H _/]+]q29310#.54632q>-yxi71->2.U K zm5D.+//10#+V!@   //310#'7'77'+V5555X7777  //339210'7##!'77RJ75}o}7L)  //339210##'7!)T77L}57}RB'/399105!R `'_ _@   ?32910#&'7##&'7`$C-j$C6e ^mrY /3/10#!+ToPN) /3/105!#NTP@  //]210###!V @   /33//]3310###!!!VtP @    /3/]2210!!5!###tVPN6& q #/@2 $*01* H}Y '%@? H!}YP!`!`!!!!O! !! '*---- H'-}Y'%@ H }Y ?++_^]_]?++_^]_]9/^]]q++_^]_]9/++_^]_]99331074632#"&4632#"&4632#"&4632#"&@?=BD;=B@?=BD;=BA>=BD;=B@?=BD;=BoBIHCCIJyBIHCBIJDHHDBIJyBIHCCIJ!@  /33/]23103#5!#3###VPPN @  /3/]2210!!!##32#"&2654&#")J17L oU{FN`USOpiy+;^\^NXUeX`RN\V9`mZUn Q?55hUp Q?55hUPp Q?55'`#b 4@     R P?3?39993333310%33 # #Fﻶź{ybUp Q?55JF@R  !mY*:  mY mY mY?+?+9/_^]+9/_^]]q^]qq+33933333310)#"5432&#";!!!!!F'ɟ~BofzVq@:ϲdh"*0@I .&+ +&- (!!)(- 12-( kY .##kY"O_/3/]q3+33/3+33/39333333333333310&'27##7&'#&4?37327"& )FAG;%DžQj%'YG/<'#H.%-'DX)Zx -9! %~S4R,́9sL&M@(% " "'(% #kYkY"  kY?+3?+9/+99333102&#">7# !2.#"36;>B+]~J_Vb@٦J;b~ _ l #l\V13qT'_@4 &&() &$ $]Y@'''$?3/?33/]+3?993333333310632##"##54&#"#33>325R^ߙmt /jUT!5uJPZ!%*/@g- )$*("(&$ #  !,++,#$01" -mY ( %mY/*/ ?3?39/]q+9_^]+9933333333333333333105#533333#3#####5%#3!3'#3''# 4񢠠)== VZ VG{e{߿ X <t@=/  )6)"")=>%")96,3^Y, kY kY ^Y?+?+?39/+3?+99933333333310#!2#'32654&+#"'53254&'.54632.#"X+nk!s|^59Gol^.W;B9e9GNIqj^.\Џ2q\~A%1=R@7#iXP^aLTe{Vb\\<;wr "X-I"H wcVXL@*    mY/   ?3?39/]3+3393333310!!####53333V)s53T}'oq@@       @ iY?+3?99//_^]99933333331077#'%5'%!5!!IIǸJ:J:7H9ťlϦmFPṃl1y9_@6#0 0*+(7:;))(lY( 3kY(+kY(lY?+?+?+?9/_^]+9/93310#"&'##>32%"32654&2+332$54$#"'>ye|5eH%əSj(ocJT4!VJ>Lol)^~% htjXrHRz@&"%-!"+Z@/ '#,-*   %lY  lY ?+?+??39/2999333333310#"'532654 #&546324#"6vlcHRRH=P~&PUqu;.}j!YWf-9xR_!&,@*#",   # -.nY" P +nY/   ,kY? O _      &kY?+?9/_^]]q+9/_^]33+33_^]qr_]22+339333333333310#3#+##535#53! 34'!!6%!&+267!7r?U-'J׏hy*V%J'Eo#on#))=VAJ}\;!i@9   "#iY @ H  iY kY?+33?+333/+9/+93333333105$%53&'!67R-FBvS?"OGRO3C + "{@C    #$ mY  mY  ?3?9/33+33_^]22+339933333333210!!3##!##537!5!3!'!73'&'8=˜ªî<4;-I"P僨#υOP0@O.&//, ..,12mY 0/0/mY00?0O0o00000) iY)#iY)?+?+9/_^]3+3_^]2+393333333310>7!5!654&#"'6323#!!327#"$547#59z6:kZ3?E{c/L-9_epNRʫXBV?9^n~a"-ܿFA}\N@*   iY @ H  iY?3+3?33/++39333333105$%53&'67BԛJܤU@MG LFf56x@B   mY mY  mY?+3?9/_^]]+99/3+3933333333310!.+5!!!!#53267!-P}b}- sZrgN1{Zdu"` dD"2]@7# ++ 34       p  /'?3?39/]39/]9/q3933333103254&+#!2#%4$32#"$732$54$#"吪SY/^^m+*լ֭ۢQIE^ZƬ֭+*  26u@E&  5- 3 5 7865 E   p 0 - * #P#@###?33/]q399?33/]39/]]]3??93333310'##3/#"&'53254.'.54632.#"#HIEF>t%'3??i\w;y+#&i-968\qZݕ"@3CF[i}N"!#$_P[hm)+-&aJ=J .@  ]Y]Y?+?9/+933103!5!!5!nCJ_.'`&{u?51-'&tu$?5FX&@]Y ]Y ?+?+9310"'632#"&'532654&pE'bDrBH1d^D 1@  p /3/]/93310#&'5673!9>HH>9)DH$HDV @   //293105673&'#DH$HDV:=HH=:#d^D 1@    p     /3//]93310&'3#67!59>HH>9#DH$HDV @    //29310%67#&'53+DH$HDV9>HH>9d^D?@%  p /3/3/]39333310#&'5673!&'3#679>HH>99>HH>9)DH$HDDH$HD(@   /2/29333105673&'67#&'5DH$HDDH$HD:=HH=:9>HH>9H0@   /2/2293333310!!5673&'67#&'5 DH$HDDH$HDhPX:=HH=:9>HH>9yH^y`@ //3993103!!^j8^@   /3/29933104>32#4&#"rуwfŠdHP @@&  P_ / ? o  /]3/]3/]3993333105!5!5!d8d7 @  /3/29933103 %! {RVj-Gn@#@  /3/99310#4632#"'&'&#"}?L3% &!" @/)3 )''#i@  //3993103#"&546323265#9P3## #>/'5)%37/333105! h//93103#בK7@ /2/93310!!#'k7n7@ /3/932105!# )@ //3933103!!n@ //3932105!3  @   ///39333103!!#knn@  ///39332105!3# K7@   /32/9323105!!# kn@   //339323105!3! n (@    ///332933323105!3!!# knn6@ _/]]3_]q/_]33333105!5! BZ@  /2/39933103#3#ّiK K >@!  _ /]]2_]q//_]39333310!!!!#'kkב"7 &@   /33/39933310!###ؑ7nn# B@#   _ /]]2_]q/3/_]399333310!!#!!#iro" :@ _/]]3_]q//_]393323105!5!5!# i)ג(7 "@ /32/399332105!### ݑؑn @@"  _  /]]3_]q/3/_]399332310#!5#!5!ӑtt(F(ޑ <@    _//]3/]]3_]q93333103!!!!k#ב $@   /3/3399333103!!33B%n#n @@"      _/2/]3/]]3_]q993333103!!3!!ّJ%i# 8@  _//]3/]]3_]q93323105!5!5!3 iג) "@ /3/339933210!5!333#ؑn >@!        _/3/]3/]]3_]q99332310!5!3!3!5!#LF B@#  _ ///]]3_]q/_]3933333103!!!!#kk#ב" *@    /3/3/3993333103!!#3#Bnn K L@(   _    /3/3/]]3_]q/_]39933333310#3!!#3!!jr " # >@!  _ ///]]3_]q/_]3933323105!5!5!3# iגK &@   /3/3/3993332105!3#3# 㑑iK#K J@'    _ /3/3/]]3_]q/_]399333323103#3!5!#!5!B㑑tK (ޑ B@#   _   /]]3_]q//_]32932333105!!#5! ki"h7 (@    /322/3993323105!!### ؑnn N@)    _ /]]3_]q/3/_]3339933233310#!5!3!!#!5jtrrBޑ"ؒ @@"  _  //]3/]]33_]q932333105!3!5! BZ# (@   /3/333993323105!333! ؑnn L@(         _  /3/]3/]]33_]q399332333103!!3!5!5!B#oV@-   _  ///]]33_]q3/_]3329333332333105!5!5!3!!!!# ikkג#ב">@      /3/3/333339933333323103!!###!5!33Bؑnnnn d@4  _  /3/3/]]33_]q3/_]333993333332333103!!#!5!3!!#3!5!Bؑtr#ޑ" //3310!!V//3310!!V//3310!!V //9210!!+ //9310!!+ *fw% #'+/37;?CGKOSW[_cgkosw{@"2Jjj#3Kk.FVznn/GW{o6Nff7Og*BZ~rr+C[s :Rbb ;Sc&>^vv'?_wwcsgokcgkk`dh_[WW\XTOSKKLPHC?GG@n?o*Z+[BrCs.^/_FvGwA#&.6>JFF'/7?KG"*2:NBB#+3;OCCG@ PQӸCи@ԯ?<;87{{|4xgkosw3ccdhlpt0`OSW[_/KKLPTX\,H7;?CG+3348<@D(0#'+/' $(,$ #  KH@Ԩx`H00H`x DAGO   L/333/3339//////////33333333333333333333333333333393333333333333333333333333333333333333332333103#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#%3#73#73#73#%3#3#'3#'3#'3#'3#'3#3#73#73#73#73#73#3#'3#'3#'3#'3#'3#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#3#3#3#3#3#3#3#3#3#3#3#fiiiiiihhffffffffffhhiiiiZiiiiiihhffffffffffhhiiiiZiiiiiihhffffffffhhiiiiffffffhhiiiiiifffffffhhiiiiiffffhhiiiiiifffffffhhiiiiffffffhhiiiiZiiiiiihhffffffiiiiffiiiiffiiiiffiiiiffiiiiiiffbbbbbbbbbbbc^^^^^^^^^^^````````````e^^^^^^^^^^^`aaaaaaaaaaad^^^^^^^^^^^`cccccccccccb\\\\\\\\\\\bccccccccccc^```````````bbbbbbbbbbb%```````````bc^``e^`ad^`cb\bc^`b%`C%IMQUY]aeimquy}  !%)-159=AEIMQAS@zKk h| OoLldi}SsPp`"eWwTt\&a# +P;;Xxؿ)H*99]'A!/L?? ,Q<%D.55 &I+648<@DHH0M@26:>BFFA "E/22@6<@ ؾ RS@  $(,0ֹ:>Gʽɹ59ȹ48+/D*.C%)$( !@ ?| {~ osw <knrv ;jj\`dh[_cg@OSW8KNRV7JJDHCGLP@4 kKKk  ׹;?HKO@ 3"&*./333/339//////////333333333333333333333333333333293333333333333333333333333333333333333332333310!35#35#35#35#35#353353353353353353353#3#3#3#3#3#335335335335#3'#3'#3'#335335335335#373533533535!355#%355##5##5##5#353353353355##5##5##5#35335335335#3'#3'#3'#3#3'#3'#3'#335335#3'#335335#3735355#5##5#353355##5#35335#3'#3#3'#3+jjjjjjjjjjjkjkjkjmkjkjjkkkkkkkkkkkkkkjkjkjmkkkjjjjjjkjkjkjmjjkjkjmkk?kkmkkmjkjkjkkjkjkjmkkmjkjkjkkjkjkjmkkkjjjjjjmmkkkkkkjkjjjjkkjkjjkkjjWjjjjkjjkjjjjkjjkjjjjkkjjjjj!c c"a c!b!`````````````b^^^\`h^^^^^^^^cccccccb^^^^^^^^aaaaaaaa^^^^^^^^^^ccccccccb\\\\\\\\cccccccc^````````bbbbbbb bbbbbbb^^^^cccb^^^^aaaa^^^^^ccccb\\\\cccc^````bbb bbb{Z//9910!!{!!@  /2/3993310!!!7L17}1mh{//9910!!hmh{@  /3/3993310!!!hKPb//3310!!L//9910! XVRZ//910 7L//9910 LRZ//9910Z79e-)@  ! /3/39933104>32#".732>54.#"wx{yy{xwV`bcb`c``dyyyyxyy{b``bcbbbV^R'/7?GOW_gow@X\PhhTl8xx<|(pp,t ``$dHH L@@D0044DLdt|l\ JrvNvvvBz~F~~~2jn6nnZ^^RVVVVV:>>> *..v~n^V>..>V^n~v&f0b@bb"0p&/&?&&&/]]/]9///////32]32]3232q32]32]3293333333333333333333333310#"5432'#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432#"5432%#"5432#"5432'#"5432377349947575#3773865567557R75577667377349944976#58856556\677675577667667+557775555885Z557w55763:C558337775555776557737+558#  //99102#"54>jmsoujlw)@  //9933103!32>54.#")wvuwwwvu}Bwwwutww)#'@ $%  //933103!4>32#".'32>54.#")R`babbab`Nwvuwwwvu}B`bb`c``cwwwutwwsbu &@   /33/]3993310#"&546324&#"326bcfdiFIKgFEgcIN_}khfJHfFffFHdhy $0:k@%+ 6+:;<51@) H168833@ H(.""O"_"3"3"  /  /]3/399//]333+3]+29333310#"'4! 4#"32#"&54632#"&54632327#"'ybbZٗ31Z-!!--!!-+!!//!!+LL=`bHgj34V// -- // --# #-S@4( $./)--!O_-&+++@ H++  /  /]/99//+]]]32]3910#"'4! 4&#"326%4&#"326327'#"'bc0!--!0.!//!.bb>KLHgj{ -- // -- //ۺ#Fs;)5p@=3$-%-"') 3 3 67"   $'0*()/3/39/3933333333333333310373#'#5&''7&'#5367'767"32654&BAe;-VL12WXByd+N P)opÉ;'--qt>}`+%* J-d}>^1N =LJŇP'$T@+  ""%& /@/3/]99//]333339333333310.54632!!#!5!"327654&qqwTVhL%Xw{TV;>wBh}VTylFFxUVy>=TVwR,8F@#0',!66,'9:,*3$-$*/3/399/99933333310&'&54763327632".'#"&54632"32654&+ !C=#"&5467>!aFXdP{XZ[Xe`Ga^%%`]ZRw;3C@&'. 45*   .#  //99//]99233]3910)7>5'#"&54672&'&5463267632#".'Fw^69Zs\=e% qtET'iCJt8v_=1op#8wL/yuzs3B'$'ykVb'NKuu2Qi}x6fZy@   /3/99910./.54632>32bZ[K6dV'!XaXoV{eAkswwucVB   //9910&'6J{FT+t}FiRmX;.@  //9/93333103#654&'#"&54632Ll^/9r@k99}M+/dyyw {7-NsB@#      /3/933/9333310#"54632#"&54632%%5_s{N/+ىs9:wJ6.'DeQovt5-Luguf7u@E    !       `//]q/9///99933333333333310##57573%377```J`X=@`^``F\^` Z l@:   lY lY ? iY?+?9/_^]3+3_^]2+39333333331035#533!!!!!!#\\ɳX꒶ݤ_@1   ^Y   ^Y??9/]3+3_^]2+39333333333103###535#5333#b?Y@0   / @ iY?+?9/33_^]]2299999333210"'!!&#"#>32332673V,* h dU#**g dNN ;323#>=4'7T#R|klfWD7S`&"d_Mq^`DVgIjt++B4 ,2)%mck,fcQ;!VF j@7"   !"    dY]Y?+?+3/33?/99933333333310%267#"'#&5#5?333###^i6_A6Hk%,Q NQVHu;yE@$  " ]Y]Y?+?+???993333310%##4&#"#33>32w 1qʘ}8Z@PZE@$    " iY?+???39393333310!#373 3#~ ᜱ/Fk`J@'  " ]Y?+????93933333310!#33?3 3#Z}=F_DfmmӲNTs+#}ND C@"    "iYiY?+9?+9?933331035!5!!#NyPsJ =@   "dYdY?+9?+9?9331035!5!!#PNTwG}}Z":@   #$iYiY?+?+??9999333310"32>54.'2373#'##"$5ʞ[\ƙ;  9奻G+\<[ncJ`pVa1^"@  ]Y ??+?933102&#"#3367>C2%#0j  4Z^ 69Jy"QOH8>]I#*@ $%  kY?+?3?399310!#&'#367367>32&#"ǻ? 6}.865ra:$#%' KsHrgZ ,'{^(*@$ )*   !&]Y!?+?3?399310!#&'##337673367>32&#"Ӽ2* Ӻhm Ľ  ;g`RC2%LjMbJkZW>Zk#OMIGTR oh $^@2"&   %&$!  ]Y  $!dY$??+?9/_^]+99993333310654&#"#527&546323673#2('3>Oxk)3rqwdKT'WO@+99TZpit4{T;@" iY8i0??9/]q]]q+993310!#3!sVyJK@- ]YM]}??9/]_]q]_]_]q+993310!#3!y鴴J7q\^;@  ]Y aY?+3?+?9333310 746324&#">ыYO^xeGO?*`u{#^Qrr!,@ _o/]/]99//993310'%'JII)IImmml!h`-@! / O _  @/O_/]]/]31034632#"&ӕ+?,+?:0,?!?#;77;6=8{%@ / O _  /O/]/]3104632#"&5ij?,+?:0,?ii;77;6=8#@  / O _  _/]3/]310!!4632#"&@?,+?:0,?ok;77;6=8_/]22105!53llT;@?39310 !#!b;{ T@?39310 !3! &@  * /33/9]993310#34632#"&Nu3A>>AB==BX7BGI@?LJ$@ % /29]9933103##"&54632u3C<?BD=;B;BHHB@KJBIHC@KJfu-"@ /3]2993310!55!-9?9910#3Nu35?9910#3Nu35- ;@)@P``p0 _/]3333/]qr10#"&54632#"&54632'673#3..2:&)88'.2:&'8 09y3046.52255/6.522dY ;@)@P``p0 _/]3333/]qr10#"&54632#"&546327#&'533..2:&)88'.2:&'8y903046.52255/6.522gYd+G* @ 3 @  _   /]33/10#"#6$!3 N`" zt3 @  _/]22/103 #&$+ #bO 3Ľtz 9@'    /_/]q33/].]].]]10.#"#!2Oh. $@ /3/99993310!#!5!3d+\+ $@ /3/99993310!#!5!3d+%F $@ /3/99993310!#!5!3n!ZZ @  /3/999310!#!5!3n!DN @ /3/999310!# 7 3g\=H`3R "@ /3/9/3993310!#!7!3bH3o`RN @  /3/99993310!#73^J^sN @  /3/99993310!#5 73gRۇjh0hF@  /3/999310!# 73qZyfkFq @  /3/99993310!#73q_ZGd)5 @ /3/999310!# 7 3RkGHyN!5 "@ /3/9993310!# 7 3Rk`/L-!P "@ /3/9/3993310!#!7!3ysdH^- @  /3/99993310!# 73`wcFFH@ /3/999310!#73vq=Df-q @  /3/99993310!#73qFsGVH!% @ /3/999310!# 7 3>{GHZ1#% #@ /3/9993310!# 7 533X3'5g% #@ /3/9993310!# 7 3D{rVJ1}q' "@ /3/9/3993310!#!7!3by R1X/@  /3/999310!# 73HՇH7%q @  /3/99993310!#573q>{G\1# @  /3/39999310!# 7 36}MH)R/) $@ /3/39993310!# 7 530XAuP/j5 $@ /3/39993310!# 7 3NN-qT+o5 $@ /3/39993310!# 7%3Nu7T+}/@  /3/399310)733+NT-)q@ /3/999310!#73qB=T-)P@  /3/999310!#!'!`sboL #@ /3/9993310!# ' 3\H6fy3L #@ /3/9993310!# ' 3VH)hy?L #@ /3/9993310!#5' 3THhy-^ @ /3/999310!#' 3P5fy=Lq@ //9999310!#'3q^hy"@ //9/3999310!#!5!3qT; &@ //9/399993310!#!5!3`/h{T &@ //9/399993310!#!5!35%"@ //9/3999310!#!5!3@P@ //999310!# 7 3i``ybVL "@ //9993310!# 7 3e`;H`FF $@ //9/39993310!#!7!3gb+\t]^L @ //9993310!#73^'ezL@  //9999310!# 73e\هseRdZLq @ //9993310!#73qe^=ddZ/@ //999310!# 7 3Hu7T`H?9 "@ //9993310!# 7 53Ru9HpHF? "@ //9993310!# 7 3Mw\sX=T9H? $@ //9/39993310!#!7!3lwo V=1?@  //9999310!# 73\w߇5:=?q @ //9993310!#73qXw1-B=+5 @ //3999310!# 7 3N}5H)1q5 #@ //39993310!# 7 53N}<Au1]j5 #@ //39993310!# 7 3NN-q -+o5 #@ //39993310!# 7%3Nu7 -5@  //3999310)7331N߇ -P5q@ //9999310!#73qN3 -yL@  /3/999310!#!'!nwJ{L #@ /3/9993310!# ' 3nH J{3L #@ /3/9993310!# ' 3nH)T?J{?L #@ /3/9993310!#5 ' 3nHu^J{-L @ /3/999310!# ' 3n5RjJ{=hq@ //9999310!#'3qo;L{L@ //9999310!#'3kNf{F $@ //9/39993310!#!'!3bj\L "@ //9993310!# ' 3\H5gyFL "@ //9993310!# ' 3VHiyPL@ //999310!#' 3ifrq\%Lq @ //9993310!#'53q^g"@ //9/3999310!#!5!3XV9ZB^ &@ //9/399993310!#!5!3cf)9% &@ //9/399993310!#!5!3b-%w"@ //9/3999310!#!5!3ZV@ //999310!# 73f^ q%^`V "@ //9993310!# 7 53o^h^xX "@ //9993310!# 7 3q\3Hmg1ZV $@ //9/39993310!#!7!3bL+Vm\V@ //9999310!#73'^{^\q @ //9993310!#73qu\/3g7 @ //3999310!# 7 3=q+\=LD7 #@ //39993310!# 7 53Po+^-L i7 #@ //39993310!# 7 3Po?J?LL)7 #@ //39993310!# 7 3PqX/XLBb7@  //3999310)7331PqLb7q@ //9999310!#73qPq?L{H@  /3/999310!##'!y\1F #@ /3/9993310!# ' 3{Ny1PF #@ /3/9993310!# ' 3{Hb1F #@ /3/9993310!#5 ' 3{HtD1\F @ /3/999310!# ' 3{HX1)Fq@ //9999310!#'3q{91@  //9999310!#' 3wbL^=5 $@ //9/39993310!##'!3ws;s=9 "@ //9993310!# ' 3uHXqHETJ9 "@ //9993310!#5 ' 3uHHG}9@ //999310!# ' 3uHHG9q @ //9993310!#'53qw>K@  //9999310!#' 3[VHZdbVs @ //9993310 '53#/[{b $@ //9/39993310!#!'!3[HVbk^ "@ //9993310!# ' 3[VHB1by@ //999310!#' 3_VHLdy}Lq @ //9993310!#'3q^d+"@ //9/3999310!#!5!3LR= &@ //9/399993310!#!5!3aNA%1o5 &@ //9/399993310!#!5!3qÇ"@ //9/3999310!5!3#d+VL @ //3999310!# 73e\-yfL #@ //39993310!# 753e\ }VyfL #@ //39993310!# 7 3e\j?yf)L #@ //39993310!# 7 3e\=J3yf6P@  //3999310)7!31i\y whPq@ //9999310!#73qi\;wh/@  /3/399310!##'!l-T5 $@ /3/39993310!#%' 3H{-T75 $@ /3/39993310!# ' 3HJ-T+ $@ /3/39993310!#5 ' 3H/P% @  /3/39999310!# ' 3}H)/R))q@ //3999310!#'3qÁ)-T/@  //3999310!#' 3TH7H' "@ //39/3993310!##'!3eyT19% #@ //39993310!# ' 3{Nq}1JV% #@ //39993310!#5 ' 33h5@% @ //3999310!# ' 3{H#1Z%q @  //399993310!#'53q{Šy1H@ //3999310!#'3vfD=- @  //399993310!#' 3mwbFFcP "@ //39/3993310!#!'!3sXdH^5 #@ //39993310!# ' 3kL!-L5 @ //3999310!# ' 3kL!Ny-q @  //399993310!#'3qs!HVF@  //3999310!#' 3RZZjfyN @  //399993310!#' 53LRHh0hjN @  //399993310!#'3}^s^JR "@ //39/3993310!#!'!3bqlV`sN @ //3999310!# ' 3\H3`Fq @  //399993310!#'3qZ)d @  //3999310!#!5!3D $@ //399993310!#!5!53'ه) $@ //399993310!#!5!3sD $@ //399993310!#!5!33\+Շ\q&~ ?HG%+555q&~ @0/%+555q&~ A0/%+555q&~ B0/%+555q;&~ W3-%+555q;&~ V3-%+555q;&~ U3-%+555q;&~ T3-%+555& ?x@ +*%+555& @x@ %+555& Ax@ %+555& Bx@ %+555;& Wx@ %+555;& Vx@ %+555;& Ux@ %+555;& Tx@ %+555y& ?0/%+555y& @-%+555y& A%+555y& B-%+555y;& W%+555y;& V%+555y;& U%+555y;& T%+555& Sx@ +*%+5555& Rx@ +*%+5555& Qx@ "%+5555& Px@ "%+5555y& S0/%+5555y& R0/%+5555y& Q3-%+5555y& P3-%+5555{ <@  iYiY"?+?+??9933310%#"'532654&#"#33>32 Ͼb:GUfo 6s un;\u{N;@  iY"?+?3?3999333310"'53267##33&53b:GUfm {unmV"U@- #$/?iY iY?+?+?9/9/_^]93993333310!"=332654&#"#33>32㹶 5uĵɾռ[v&W@/&  &'( ]Y   #]Y#]Y#?+?+9/_^]+993333310!2654&+532654&# '4632#"$5bPmXϴȻӝy з3ǻjL@2 @ H/_ /]33/+33/]/29310#&'53%46325>5"&!!VCC=-27jx8A-=4_4.D5mz L0+/jO@3    @ H/_ /]22/+33/]/293310!!46325>5"&673#j_F>-17ix8A->:"CVZ4.D5mz L0+/j L@2 @ H/_ /]22/+33/]/29310!!%#&'53%#.54632j_:VCC=-A8xj72-=Zݩ2/+0L zm5D.jO@3   @ H/_ /]22/+33/]/293310!!#.54632673#j_ >-A8xi71->9:"CVZ2/+0L zm5D.h! #@ o@_/]]q]2104632#"&>73#8(.2:&(8+r%)Ews5/6.522L7I=6Z 3@   p   @_/]]q33]]/39/]3104632#"&3673#&'`8(/1:&(8{ri~a3<h6/8-422Js~?`f1 '@    /]q33/]333104632#"&%4632#"&!!8('::'(88&'::'&8q`h6//642246//6422o /M@5vO _ o   , O$$$$( H$)!$@_/]]q3/+]3/]]33]3104632#"&%4632#"&".#"#>32326738('::'(88&'::'&8:+SOI"11_ o\-UNH /2] nh6//642246//6422$6.pz%6/rx?G,d@X  @?$@IH $ 4        :` p O  ( H  @_/]]q2/+]q^]3/_^]]]+qr^]10".#"#>32326737673#'MIF&*h hU*PIC+&f e1n#7w$,8pz%6/pz5;~EO1  +@  0 /]q22/]]10!!%#&'53`y71Yd1  +@  0   /]q22/]]10!!>73#`s= aw[#.KZ (n@$%O_ @0,/H@# #H %%% %%%%0%%% _/]3333/]qr/++]qr]9910#"&54632#"&546323>73#&/3..2:&)88'.2:&'8{5s38q6B(,@3046.52255/6.522#N78M#@KJ@/ @` _/]3333/]310#"&54632#"&54632!!3..2:&)88'.2:&'8`3046.52255/6.522HXA@-  ( H  @_/]]q2/+]3/]]310".#"#>3232673!!'MIF&*h hU*PIC+&f e`$,8pz%6/pzב/ /@   _ o  @   _  /]]q33/]3104632#"&!!h=-08:.-=`L<6=56=8)/ #@_ o  / ?   /]33/]3104632#"&!!h=-08:.-=`<6=56=8^ $,m@F ) ,-.',,,$0@5 ,"?O/?@H _  /]3333/+]q33/]]]q39/]933104632#"&%4632#"&#"&'3327673#{8(/1:&(88&/1:&&8q Vg R-[qe76/8-42246/8-422xz96ol`wX^ $,m@F  %(-.)&&&$0@5 ,"?O/?@H _  /]3333/+]q33/]]]q39/]933104632#"&%4632#"&#"&'3327#&'53{8(/1:&(88&/1:&&8q Vg neq[3L76/8-42246/8-422xz96oXwm_j #a@A  #$%_#o######//?@H _  /]3333/+]q33/]]933104632#"&%4632#"&!!7673#{8(/1:&(88&/1:&&8p_R-[qe76/8-42246/8-422jl`wXj #a@A  $% _o//?@H _  /]3333/+]q33/]]933104632#"&%4632#"&!!%#&'53{8(/1:&(88&/1:&&8p_eq[3L76/8-42246/8-422jXwm_^; %M@/"%&'  %@ H%% @ H _/]33/+3]+293310#"&'33267#.54632673#q Pn]]>-A8xi71->9:"CVv~x5/22)1/+0L zn4D-^; %J@.  &'#@ H @ H _/]33/+3]+29310#"&'3326?#&'53%#.54632q Pn]]DVCC=-A8xj72,>v~x5/2231/+0L zn4D.^; %M@/"%&'  %@ H%% @ H _/]33/+3]+293310#"&'3326746325>5"&673#q Pn]]P>-17ix8A->:"CVv~x5/22)5-D4nz L0+/^; %J@.##&'#@ H @ H _/]33/+3]+29310#"&'3326?#&'53%46325>5"&q Pn]]RVCC>,27jx8A-=v~x5/2234.D4nz L0+/F@%iY kY ?+?+?3?999933210!# # ! #"'5326! 3}w9NQnEB4=;Q>T4fi<{6wm"=HTJE@%]Y ^Y?+?+?3?99993310 # #"'532! 3 # #_v="l#1c bJjO@*   kY  kY?+?3?9/+9933333103 #!##! 32654&+o&-Mը%ĶH!f^'W@0 %%()  ]Y"]Y?+?+???39933333310"'##33>323 #"32654&w @n٣)N==6ZP۸#-|@F   iY:    kY  kY iY ?+?+3?9/+39/_^]^]]]+9333333310!!!!!!#.54$)#"!3Ty ݷq8^2Ξӝ!^'.@H  +# ,,#/0  +^Y++++ "]Y"" (]Y %]YaY?+?+?+?9/+39/_^]_]+9933333333103#.5463!632!3267#"$'!!3!"%"!.9~ηvXmXo swӁ/ wwm-&!PjZq=@     ?3?39933333310!##3'773'kjgi<m˰m#J;@     ?3?39933333310##3'773ɢZV-J!XZ,T@. #-.iY + iY +iY+!&kY!?+?+??+9/_^]+933331063 #"&'532654&#"#! #"'532>!}L1PMJ~+z8USmE@4=:Q8GH כ1Wul PJ$V@1 %&aY ##]Y# dY aY?+?+?+?9/_^]+933331063 #"'53 4&#"#! #"'532!R;Ќjl N;`vCk%Nq <=/cq$u@C !"%&iY !iY!:! !!!!! iY #?3?3?+99//_^]^]]]+_^]+933333331063 #"&'532654&#"#!#3!3%L1PMJ~+z כ1Vj J @P !"aY ]YE  aY?+?3?399//_^]_^]]_]_]+_^]+933333331063 #"'53 4&#"#!#3!3R;  Ќjn~ M<q <=/J7 6@  " iY  iY?+?+??933310%##!#!%IJ 6@  " aY  ]Y?+?+??933310%##!#!ȴ{PJN>@!  iY "iY?+???9/+9333310%##4&#"#3$32|f-vv"2;\VG@%  " ]Y]Y?+?+???9/93333310%##4&#"#33>32w 1qʘ{8Z@PZ (@     @ H /+]22939910#'##'##'5R!11!11!P!ffff!)Vq@H   _o   sY  ??+?9/////_^]]999331023#"'575573%%ZZtD۰Zj&(LJJJp͑u=G@ G.@`/#G/@f)G0@G@#G@ ^ ^ p 8~ ^   D *" (L \t > < J 4Copyright 2012 Google Inc. All Rights Reserved.Noto SansRegularMonotype Imaging - Noto SansVersion 1.06NotoSansNoto is a trademark of Google Inc.Monotype Imaging Inc.Monotype Design TeamData hinted. Designed by Monotype design team.http://www.google.com/get/noto/http://www.monotype.com/studioThis Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.http://scripts.sil.org/OFLff  34566778:;YZ[\_`ders}~NOGHTU > ? W X o 45Z[  `bddss!#$$%%&()+,-/1256689::BNHIJJKQRRSSTT Ncyrlgrek$latn4 kern8kern>kernDmarkJmarkPmarkfmkmk|mkmkmkmk        *:JZjz  %~ & )` +B @" P Q ^ _V b  de dF`bddss  %(3!-:/6G8:OBNRHT_%$=D]4KBj77NNSV\_27 BI^alq~!WYZkl""(UZW]f]kngqk{QQbhssvvl $****0*****************6<***BBHN*N6**T**TT****Z**T`````````````ff*lT* &,28>DJPV\bhntzbn,bn "(h.4:@FLRnX^d4jpv|JJ"J<jp. $  *0:6<<<BBHNTZ`ffflr>r>rx>~x>,,,,f""""n:4:nnnn &.,2,2,2,282&.&.&.>.DJ(DJPV\nBVbnhRntz@bnF,FlRnt "(.,24:&,2v|@>FL>RF~>F8XJ^~>djVpv|V"hnbhJ^bhnbhnbhnJ 22$*06<BHNTZ<`nfnnlrxb(~nN,.,.,..,.,$n*n  n6&  ,6  268>DJ$J$PV$n\*dbhzntzRn.RnnRnnl2n>8J2 ,"(.4.b*:@nFL*nR*X^h.d.jp.vV|@ Vj|xdj.(T0>V\p"J<@ Nd.L""$*06<xBXHNTbn2* 0,6Z@0`flrx~R( &<,nr2>8,,>&.Dn"JPV\bhn4tz,t\D,n, l tx, <\nBbnf"lr(>.~>.4:bn@FLR>X^<Rdjpv.|v..|2\Fpv0nBnRn8n,n* $ *06<B6Hbhn>N~0,TpBZ`Bf,lrxZ~D|4v@b,n*n..F4@L(Zn4@4@4@N>>RndjZ4RnnJJ &,22t8>:D JPZ.BVBZ.*N\N\bh$n"~<*<*ntz<b*.2B $pr0,T0,0`T0`T<BXdx4n"4,@JnRZ(<BXdj\ "(.4:@pFLpR8X8XvhFL.X^d^N~0,6Rdhj4pv|djdj2.vhFLX^4J^N~4~0,Rn4FRn~~nJZN, (h.  ( "   " FL@ $FL * $FL * 0FL 6 <FL~ BRn BRn H N^ T Z ` f l,2|&, rv| l,2&, xv|&, rv|8 ~J\ "V  V  bhJ h bhJbh BJ z Dtz D   @&X N N  N n ~b *~ n r n  *l~!!!!>!! !&!! !&!,! !2,",!8,!8!>R!D!JPV$!P!Vl!\!bl!\!bnR*!h !nr!t !z0,! !z0,!v|!x>!!$!!*!n!!x!Z!B bhnJbhn!ZD!Rn!!:~:OfdtL~L  XX44[[|FDD| P  < ll::gg:jII00vhv\h8Dh8lh,0hlLvv H%%l0~R XXl[[l l  llLX0@0:Dx@\D@D@@v@l@lv @ $DD,<Dn ,:,XNNN,llX,X<bbHH8X\lflfb,b4<DTDl@[0[[<<|Xn,pnl<0<DhD<h l, <l< nl l`L,4< <p,,H,:> >:0v,vvLx<v<%,,DlI,I0\h%@l%@|@D$(D DPXX [ 4P[ l  <lPv vLPD jP:vH,h0`,h|[,0,lvxw,hTbth!!&&5 6,@ `@FFp<n< V 8 .8pDN${ {55IIN&S@ + 94,,,<,l,@ l(,N@("\",aIppCCD@ll|hq p:dnnXpp/XXzd~TG0G,,$|,,T@@@|jhVThTV]]It  \\,rlblpvp@p0pppp]h]pDpHHH|h|HHlvTl>>pXpblHRRl[p0@0"Xl,  p@D4:l,:,:pppglg%Il@IJ%dd## Pb`aHNTTHNTZ`flrx~Xl0ll *l \+D,l XN,0 $=D]4;CHNOPQ?ARCCUGGVJKWMMYSSZWW[YY\de]xy_{{ab  &,28>DJDPV\bhntVzVVtPPPPPPhhhhzzzzV `~du~uTWS&n~B~x>~H-J:J@J\J:JJJJJfJ<J6;JJ  *^JTJrJbJ X^ $=D]4679;<*+>FI@^aDH "(.4:@"FFLRX"^"@djpv||^^^vvv^^vv-x~x!qL{wJxdxyX*\\#9p8J^J\J^@R%mF@JJJJ`J ;A$=D]4KBj77NNSV\_q~]""eU&QQ'bh(ss/vv0   1      & , 2 8 > D J P V \ b h n t z    "(.4:@FLRLRX^LRdj@F pv|@F            J J J J                   $"(.(.(.(.LRLRLRLR @F @F@F@F@F      " " " "   *0 (. (. (.  (. (.6 26 26 2 , 2< >BF 8 >@F JLR JLR JLR D JLR JLRHNTZ` VLR \ bX^X^f nlR h nLR h nLR h nrx h nLR @F @F @F~ @F    pv pv pv | | | |      @F @F @F @F @F @F           LRLR zdj                           (. (. (. . . . . (. JLR D JLR                @F @F&,2&,2&,2&,2,2       8>HN  DJ  PV\b  hntz &6 2 D J \ bX^LR @F |       "(.4:@FLRX^djpv|   JLR  @F(.$ , 26 2 b^   :@FLR6 2 @F     (. (. JLR JLR   pv pv @F @Ftz< >BF 8 >    (.   " h n  |  $*  (. P VLR06 pv  "<B(.(.HNTZ LR`f@F@F@FLRlrx~djdjdj@F@F  $pvpvpvpvpvlrlr|LRLRLRLR@F   `fLRX^ &,28>DJPVPV\bhnDJtz4:dj@Fpvlr| LRlr 4:X^LRdj@Fpv| (.LR"LR@F    "          . .  (.  (. (. &:6 2< >BF 8 >@F< >BF 8 >@F 8 >@F D JLR JlR b^ \ bX^ \ bX^ h nLRf nlR h nLR h nLR zdj t zdj @F @F @F @F           pv pv pv pv | | | | |        @F @F @F BF BF          @F   h nLR h n  i<iJJ(N33ss''//11BB??ddqq}}FF{{NNJJ;;0 0 0s0000?000  000,/0100mm0d0q00B0FF==;;}h}0h0h0F0=0dd{{yyVV==BB{{yy V0 V  ``!!DD%%0F00 VJJ^^  }}##??BByyhh{{BBLL%%dd1130'00000Jhh0 $=D]4KBj77NNSV\_q~]""eU&QQ'bh(ss/vv0   1      & , & 2 8 > D J P V \ b h n h t z h , h h     & & & & & & > > > > V , b b b b b b n t t t t , , , , , , , h b b b n n n n h t t t t t h h h h             & , & , & , 2 2 2 8 8 8 8 > > > > > > J V V \ \ \  \ J J J V  b     b b b b b b b b b b b b t t t t t t t t   & , & , & , & , & , & , & ,           > >  "  "  "  "  " V V V h h h ( . 4 h h : @ F L R X   ^ d j p v | h 2 8 L   j D V ^ \           j     b  & , > t h h  & , & ,      h   b b t t   & , & , 2 2 > > F  h  , \ b t & , V      n    >  t   h 2 V b h h h n  h h t t $ *  D h h 0 6 < B H N T , j Z 6 6 ` ` , f l ^   r r r x &  D 0 ~  h r r              h h z h 6 h  P  6 h  , h h z  h  b h h t    n  h h h n h h h h h t t t t t z h            & , & , & , & , , h , h 2 2 2 2 8 8 8 8 8 > > > > > D D J J P P V \ \ \ b      , 2 b Z J003000s0'0000/0010B00?000d000q0000}0000000F0{0N0000J0;000 0 0000000m000F00=0;0d000{00000y00V0=0B000{0y000000 V0 00`0!0D0%0000J0^0 00000}00#0?000000000B00y000h000{000B0000L0000%000d001000 Z`"$&(*,./125678DFHJLNOQRUVWXL"LRX^djpv|jppdppX ,D  5D\N $=D]4KBj77NNSV\_q~]""eU&QQ'bh(ss/vv0j1jpv| $*06<BHNTZ`fljjjjjjrx|~NNNNf6fjjvvvv||$*`BBBHHNNNNNZflllZZZf$$0jNjjjjjjjjjjjj &,282828>NNNNNN>NDfffJppv|PV\bphnt*z6BHflB6jN  *     " ( . 4jjNN : @ F\ L Rj X ^f d jH p vjv |  p $ f  BB$      x6       N $ * 0 6 < B H N N$ T Z< ` f l r x ~ * <  F 06BHl   6  6 $   p    x | & , 2 8   > > D J  P V** \ b b h n J t00 z  66  nB BB H 2  J  T ZZ``fl h HZf xz%{N4RjHLbH$b=&Db@HE4HPHpppp(pbp\H`HupNpDpp\pDpH>2(bRHf  \Hd0L#3DH Hh]1 RHHH~_ pv 0H3HHH HHH=llHDHH\HhHH`u=HHHH)BHHjL H3tHH H/|@HHJ3DHpppbrhhppppJ 0lppR\/4p:bDXE 6@EGIKMQSZ ]]4:6<BHNTZ`flT6rfx~VVV V=VVpLV,bVV= VVDVbVVsV p`bss!#%% )+!/1$66'::(BN)HI6KQ8SS?`bss!#%% )+!/1$66'::(BN)HI6KQ8SS?@@ $***06<B***6HN**TZHTT`Tff*fffllfffff<<x:Ot`Txx@::@:0@TD d, djdd  $$&(,- 25"89&JJ(RR)TT*dd  $$&(,- 25"89&JJ(RR)TT*+    $*06<0 6000BHN6*00HTZ666666* +~t`V4\4H $ BHfl )`dos""PEKNO<-2"FEKNOFtsdtdpqt2200 0"""<"^^4 ,TT,T 0 0 0 0 0 0"""""""4<zTT 0 0 0"",,"""^T4T4 0""z   " !"!<!B!DFHIKKNNPS UU$WW%Y\&^^*+78=DJNORST^_`adnostwxyz{|}~$(**,,..0022446;==??CEGGVV[bddffhimmooqvxy{|~~      !! PQ UV]]__ggimosuuwwy 1P\bhjlpq{AFJLLNNPPRRUUWWYY[[]^cceeggiikq~//$79:< DFGHJPQRSTUVX  !$&+-/13568 : CDFHJV_biyz{~ TUV]_gopz|  "#$%&'()*+,-./013579=?AGIKOQSUWY[]_acegikl n p ~-Z&*24789:<$&*,.02468:GfmqrsuxQ\^iy{}    FHJLNPRTVXZ\^`bdfhjlnp~7$&q~< &*-2479:<$&68:G \FHJLNPRTVXZ\lnp~4$79:;<=$&68:;=?C U "$&(*,.0lnp~%&*24G\FHJLNPRTVXZ\-<$C U "$&(*,.0N &*24789:<$&*,.02468:G \^FHJLNPRTVXZ\^`bdfhjlnp~!~~$;=;=?C~ ~U "$&(*,.0"$&*247DFGHJPQRSTUVXYZ[\] !$&+-/1357<>@CDFGHJ TUV\]_ "#$%&'()*+,-./013579=?AFGHIJKLNOPQRSTUVWXYZ[\]_acegikm~$C U "$&(*,.0"$&*24DFGHJPQRSTUVX !+-/135CDFGHJ TUV\]_ "#$%&'()*+,-./013579=?AFGHIJKLNOPQRSTUVWXYZ[\]_acegik"$&*24DFGHJPQRSTUVX] !+-/135<>@CDFGHJ TUV\]_ "#$%&'()*+,-./013579=?AFGHIJKLNOPQRSTUVWXYZ[\]_acegik%&*24G\FHJLNPRTVXZ\   YZ[\]7<>@ m  < << <4FGHRTH]3579=?AGIKOQSUWY[]U( (DFGHJRTDFH( (V]#%')+-/13579=?AGIKOQSUWY[] ( ("( (   ( ( F@F`F( (  fmqrsux QV_bdipqrtux Q%V_bfimsvyz{|}~ !qrxQV_bi -V_bfimsvyz{|}~ !Pfmfms~~V_bi~ ~ V_birx Q V_bfim    y~ y~ y~    y~ 6  ky}     ghijnoprtvz{|~   i{    #iy{  N22 giop{|22 /  ky}      oy  }  n  = opwy}  !~~~ ~ops7 opw}  % gp| g|       p'  j~       I(W(Y2Z2[2\22%('(72224(5(Z([(m2(I2W2Y2Z2[2\22%2'272224252Z2[2m22  y}  5  gjz|~      op ghinoprtvz{|   ! gp| %  y}        %nixz{  g|   )  y}      j~  }   ghinoprtvz{|     p*  y}        }  )  jy}~    @  osy}         o}    +  oy}   Lcyrlgrek"latn0aalt2ccmp8ccmpBccmpLligaVrtlm\rtlmbrtlmh 0@P`ph< T"*2:BJRZbjpx&.6<DLT\djrz^fnv~ (0 $*2:BJRX`hpx$,4<DLRZbj                           LMW`bss!#%% )+!/1$66'::(BN)HI6KQ8SS? (B~FPZdnx  (2<FP ` a ` a ` a !` "a #` $a %` &a '` (a )` *a 3` 4a 5` 6a +` ,a -` .a /` 0a 1` 2a 7` 8a 9` :a Y G k l m j n o '*,./0I 4L5OZIL[IO  ; < = > V 7LMWappstream-generator-0.6.8/test/samples/appstream-logo.png000066400000000000000000000535061320016272000235720ustar00rootroot00000000000000PNG  IHDRUS pHYs  tIMEtEXtCommentCreated with GIMPWbKGDVIDATx}x6ZRRnwZ܃B$!,Fe}fwn( 6}L;;;3yϹizqSߝјMК-Ƥ?8{/h%ZZk ڗhM+B Z;FshNTa>(m@y-vmZglm;\(fdC u׏ut9a_k~\`XvZmqoKY +7N7"yD֖2H4^ jwA.gh#B[u-6C S?D+ ʒoebJ>!S-:} Í]R%/P xS𴪯)ED[tDkK\K=*i]UOH? "fN};C]\v#0V r RW+eaXrj8Q髓R҉ێP!6'5xAEDkDGeVi@J SQ~-^b1?w`h5"c$1YG`P i32 f#s)=ԁtkwHņ^ {Bqڸx<Bb]|ףPdJ~ Xb,bKG8YX5"qwiоcA#Jio\ѯ nFpCDw.crJt¶@Sk!^ "L7 V2.4>BL#z\df2$HBE+d M|TδoƗ$6j}U( tyrg>* 籉4{u+zo (^KˉOq60+IYH2 9эDBHؒįt2@L2[#7zlO]&:5]:'X2MDH`[_PfRfQP|ZYDBfJ`-OWT|DY(~q )B#_͉`?g2 ̚M[ sXxy{?8"LT aHhQJzڈ$Rp|\'WyM= ],T3-J̬8kĢw 69F/(P)z߃7/ϐzo쌏^;xAxeY"@Lq? )u7^XTǧ >|7thmqwbe k_fn`:-ܻF'Ms|vu`3~$X /b_ݕYZZ0*a]YqĢ bd:~c̞~t[k &gNAƀowOd/kp//ʵ%1&wFpK] /,,7R;ip=o暦w5@]F]j^cXFV&%Xc/9GBsm62$OH䢣əRDsggts1;yxE0j(Wn#]}ptqwww>JA`"$4").CpL$a @3g]{0-~?OΈ|3)Iq-1QayXbT@ɣJ")hbnfW`hMKMI9/4~$4:Q SM2h|F[{ _^rl\|061--)8:2>%-Tr !εɶgq2Ml6b2w37~ 6v`ffo߾@Ett4[ ԏPU%>3S62 iy9v3r~cnYqOFvm2ZŢJ⾍nSo|OX`=)ZPwCu no%8^~wF/; >`}p ΂#`~4’xIw&Pl| Ka1qnF74 l._Ľ|{IB#"|P{X"僁 ۣ;Xڭb6 U޻.BWwMREs_ޱ_=]y͆ώ\'7G APdGa,4T:^ؒw[VoyFuܳP;kEZWDDaV_Qplooncvś0/j͗V]qa7s_A v v50: aπQz"N[,a֐1*#4&㲍WxgcB3HPh ~~{%W?Y:lds|BdDhl)N{icPi|KX$xՉ&{:pgXKtj1?_-)i'Dkt'I:m:,}(FsN;s+z':8݂,ېvj`x<=q!ﮮ¢ҹ4aE7$d2n6Wbc e`kd~Yׇ @d ےA֩MnE7>+az$O]{.$$YFf%R[lAHs-]*Iarse{_3z47?J{A %@?E8]i[/+lB wWjW(ZG<m  {t^ٜ]tD?iIG{ _ۇ'!7<I ,D>Z?)NaaB PA؜_P \,H.7^jX$ciS)"iR1M\,G['c90SA[GArш,Мھ,tIi~eCU(G<1ʮ#Cz15,!hm`k6~)l1㥙뉅u4fr'4ap]?f'!Q~#waʶYln "MYi! e%@y*:P@,օ*N;(o6n#MJ3(("/L+D, SDF9\pLJmE%gi(,TGіDOj~wAԺͷg5)0mn'(i{ )LaKzwmf| ׉ mq +,Τ|q2&•h` )$vuMjS/L{4&@%QVGc9H 22ҹs4ZdsWpTwm+M`)uɘRݏԝȁqo|lωoܣW8asc ۉ`~3zA>нV pYDgcT0JhҞe5 ّOF32**j }DJBGC~m"oLORx<"X9;=>Zd 96bD&~FQ]Y@BɯyѱŷRs$9yʋ!h+M ^߾=&x$y&z΍٬J,`Vx0A 0BiŰMv%>3+smrUL$$E8xkf4ҠdՏ o:;ocf'0r=>,y/3`v5٬}Sz: _w1.G(CEEDGon;;aGlK$^AE%xƌ(R)!ifRN"W(vK4\!!̃Y&f@56&B|ि2=A94Vo?T-\ipԊt583'tT4GMpuz)tvS/`>,mhL}ژ'"I늤p?7sv+T^w[0tMȕ/tx{A/5 H?vR9Oԍɓm˩+Oqn6m*ܵkt˖Et; dSXbs%ODY=} \O#!T+* 5| Ϲx6.*sss{gN`kh#Z!B>Y*//)D(. vҶ29xKO= /qAaxҳ^;gv/7~i&,!@n# M#%42v+A%!1tхwۺ5kܹST_p݂OR ì29$[Y"ͤ~u{uly] a19&EHȀ^ gee 666d!y9yE(ۍ3aw':qnFUI6!rcsօ'mm{aM\ghК u* ܆\;B9%߳ ”bgg[6I/?"14(ֲNN9,"wv{_B-*#)-¬dMWW4o Abbz~~hXחswwYٙ3x)i(P Na46&-U$f tpm;G?(#, R:d??өԢ q'CN[P.LB}/'[d1<# csaql=Ȭgjw$u2 M,SP*}(x7)Lٔϕm {Ń!iXa)CFNg'ȵgYd]LT#A_RK]'Ӑ)q?Q?͕}t=[\Fk?QJAU;4k/d kS(F2%6fհefxTUAe<2r$ /{tB`}K ,C cɰB@Psq)9k\J_ =<A;VCCӳTl^n͟o=Yqa\]>eY\-Voqk-e8^>= !KxPOt>傁S2smlkhyR Faqq555'ݾ}{8jfHB(݅B|hgXMc|]4Dpt3 0PыI %Tڕ ϭ5haitg-mJ2S2JA&$=|"t{F"wiDZ8Z#,ARXB!N͔b @~avq# 60]]Ϙ\8FCY!Dp e.9.ԍcd4PSw8&l0ඔ-S7ԮgneAb;Z7:pDH J5?Шd09$ 4P7{PPg '0Gp'r λ98,Rd><3Hv&="Ұ02Lм :E`xb&vlH+̌L-ft]( T.2((3;e:{YhhTo!oFf,M@=/01L\S$вG6 bs gk;bAnkRC$T{N]i.np- -N7RҙlCKzŪrᅪ*}i¹xB"xIRX[$HHʀ$*&^"2.PSI}xA.4%#yŒ4d kN@!A]#[;XBZFѬ0aj;iNXc)Дѱqё II/ ^oڴYnڵ4nP]K#JYc ]Qo>eYv9eܹ٧]a97pm|T{8o>lS5g DnQoK M{ཱྀ'RË.>rD / ##ox2I}%ߘIRKd qtL07nPŇN8` QуoCe0h}N< `Ķܨ]f0fg 8p;O.JKwsscena9 vYot~ 'Uv6zIK4(8.\ZezZܐ@{ iQaY s3v pgc [9NW:>3c| @bkP̺H$jD]$uL^$/믺wnsVqŘIL83qe_i  Zq@= H6AǏ rW<;f g~À`઻0dc9nr@Fx>7?;z9wI׃IINFRtSbRIPY0PsФD!H6 IhOi..6;UpM7y uWPf%74Qy!wFq~ӣ}Mn,9 KB|Im>-q`(&4«tnJbS5q{-DVkgh.N܍ǶPS H9EbXVA(I,at * ,I)6ZIzlTy w!`!=a"Rx5*-/lL:=x2cR*1%xL|F 'AP\^"xԽ=xf@p+x/${9N6lb$~9v>/'90K$AaQ1>{FVsp>!/3ɵ+|KW 8^~n=5M]s=omv7W6{vܘ-zksrܼ)Qn"R@,pvҋ0r%t+Pg;hڙ2q`Vl-= Zg3 aGx춆?Oz.,E1TJb N\z1@ɒ276;>6hNT]34e?NQ\͉7 5v6Ym'Z R2v%fsc.OXq;褫 s9+;4C2#>p({e'0o̝Y9" @Ar %<(0*cP,C`iλ{lᖁ',p,DlI䥰ҴpVqnN+@Ne$wT']{͛|ԑ3j6dc2"#F eQ 8{ wea4r"": }&R72M$n>.̋{9b 3ao /% |HdSLs$MTr(Zi9RIFn?pNgb$۳NV_x:W,eS\a(eə_% %7x̂\`vSt &0| \ yehg/q*2.0"pF c&izr1 ,$R ! )ɵ xHj"4"dݩ0]JG'P ry᣿..xY샑so,H{Al&$ _( 48@6MW}أK;514LzOtX'^,RrD T+ؐPsLz)$$Bjf Q*b- ]@&,:ö銝V T ݉mwXF5o)@A";ph@L"cYG0KA#"֥cR6pr#a)ʩ9B6^hmYGGc $^yBBװ,$[Hw?GvFZqoF"bag=]`5 *؜3{p3[r \WT~q` ^#RV2pu׽ w  g `[G Hkc 9(⽠(~܃*kT0dn 64;l3fĶ"=DS;Kw/Fd~;퐅x:]v̀OuNOt"҈&Fr``k a 2~KJI^`ƕ6Iۯ;lG%)xM=Aw%!{>/ˁQ[UaڀPP YUad]?ݐ]|S|D'@"630#^(MJElx`12:CZD |E2x{ L0qd[ĉ= /دT eXݖMU`\!c<ІxłKU@Q_ ao\}_ȕ!Fl}-t!oe- u <#sQyҠB]eb\E&䗀@0vb5I-Jw n+r̉UmUyo{=++g {ق;(} fZUqLM~M2N=guljF" ?kyKw =ʌU#0x_~#b[#0E7gj٢& uE]:Mp|]mif<#Bn]z~xl߅/A)i*Fx˞κ gv%w#/##JD!0 0oI^U@Yg ~{AX;/U~_&hi=b}u_S2l;dn"0] 0^1d 7[-0)ޘ:ŻP vLRBq"s( i u(W =54,M<>7pf0pu3O. =oOXx^y/00E lQK.@ P0Huਉ54ʁ^j4#dD2)#@#Sƶ7R-;kX+p`(GD%pԍ9jGAce jEXcm"0Ƚ ]bL\z)7e>h(0A`ȁQ ER0o=ſjje͡{|f*1^ T8|eЮȲ4nQ%<0~1"Z!hs%h3zsl2b˫J{+Ti j&Y :.ZClh%`ެ jFq c|#ksWɥgD2`4m lT!PWR]ۛ@EKAAU0s ű xSwK#}@902SYb20{r`ko0H-BZX:3hmT!sCbhR$@8Z)[yFa-ҏf'^|b]gn\nlQ٪F]QN. y6'9;5! WVw 7F:7R0bsp.=ߦ y[H+4>kP;f&CAj_ e >yӏXx>OA&PДL! %Y6ThH*Bb` zY5C歡i6u#1h>L(̠M ~Y ǧ-t l1`y;FHtA2XCP60T5o zO?jq|DXLް7ls-MB[Rm6A_p%Vk-pV?g-H ~?ri]_~<*2-fe ,;vϿAL9LD0[~>۹ ˒[eYO`(zg5:dG$@7B\ r>@Zf.8>oBњlz(_6!9wTays} ~riSpIJy r~s" |Ӳ'h3,d8.?q}4PjJJЮo0#$ h|:`t\[T`>Nw DkY-y]!V}'h6Z>~o?)G!.ٲ}VZŲ 3Y}h?Fy8em ڌ =3C7uOQp~^wcL<`OV` bBhU+[ $%|Qku`QBwȝf;W݇a>Rq$BK`-gzrhܬe!gGڛA\Wqj d]1uILZA[hº'ѦS2ܚQB} +ɹ Xw'*`(6*i~ 9Q{ED lt/RSBT}U딦-]XٕhF,m@يb6_!~^k_z׫e}L1d{HE u}H4J 7 _Fa9Rsu|HBF Xtzj~8 =sY.u~)-EFYB{Џz[UՔ_q3KF{|ݢ(/8 r`QU30`]\y$,w1%']Qj]V/"05Ջf#k>[ClpI9g> άU7Rg4[&ؠe+8af A+Fv]wXĕ}ߪePi-0И 1-Ȉב )$SĿ}\`l}\8o-A}f} p:[72x3X&i|.04 HbEǮcYOF-,+0BJЇWidb$DAν(AVAka^3~/a]g篱ѥ1^G֨K>Q(}P?)*i6`cXyٍYylWv? ~0{m(,$SrpJ7ق,fvBn mP2U(4iߥ^N?-ˤhGBi& (AP[;u{G^?d{!Tux4E./ANPz/ u)ˆ9+]Kvȅ j^HN>dږ :}ꎨ1Z#AUXSC룺5FDT^fZ֨[u\b,uH\?[ߐ'&AWPpQXpjҼ{zpc$8mP!% '7;$CvrHBiƹg-MY0d8*2sud4&֨:ՃC#rHz9 "@6L)8<\g9IrW:K5 2YF`T^ ZRl[w"{0a!\~7 K%|#Ieb < bKڡZCR bA<:X\s70$Ԅ鬵jOExkh6:u ;ȧkm!H+6"iԬ >ϯ}4Nq &@|Q#g& 7 QY9(u%:Uh-"5>AR]WwQ]lQs噂@D4@?zd+5Lc#  8ߴ -z8 w:aHhI^{ ?~fm:uw &]P!Ih":^H^Ag=[BaCaFP`j#ZruD]z= +`8N>(}4UM|3i[FpT'b[aXu+Jd4mt~T^_-wC8y~(f9:vm'+ԙy1#r`/T-Ȃ!5Yj}5iZt| eTE>[r`8KE. I+y{?A/~;!$IXEȟH@j>eFso _ YɪHF_y`(Ϊ5h#CX0xv`8~jGe7R-V A>v0=(U_/Zh?M[z̈́cQ+epeP;5anSP9DP(`ᬖ 4') 08`HJkvP¶'f^VsU~gNh~hZF1=dKX ,C:\pG#":ċK1u;oࢲZ`:)$f J2iːEp MYD%dO ue8>>PȁQ>M1xxWYIuX%/QP6݃BR>5]tJCYcZ[q s݀T)9B/zT( E_p ׽Aof:VEf!K`QG~JBf)_G>>KnCv_MSKOB[x"{@U`ܨШv,FC4E^Uuoear\Bs`@PQK/"@.SU .4m ?MBI26F_;mYЬumH80|cK[cJļ6L)sGBмgربϑ\tC2tFmxZ'Œh{(M?1cB@TFq%tƍD"ZMB{"(*8{Fޯ0l:"a[yeWF \56?m;ɤ/×w>Z>y,r PċS$#) ~~8nϕ3La_XHLzP̂E(t10Mt7ZVp`)(v(fOi=n}rit!=vp:CJ*L<yK Fju0q)X'YLy8jTņ~Fþ;^(2UVG.q"~v1+9 ;oc5~Zؤ U'B>r)݇΁.Y C, Cܲ%K޸b4cHjTjG"nDJ.Ĉ/a70j1o#=Lmr:),C2_&_+Ն~:0ex2ZK+4Es<WŸ3 QPH'B]XzHz(/S\E04w0nݨnm?@؃,!]S:xjVWM _B#UFu"Lypǭ ʠU"Hf2qDXҐ-EW % "د z.FNfu)+D&(7~`E3e 주VQH֟Aۯ~" i!k/{ Wpo*}q>~? =,Y'Q>*\ ƽJBB:ș:A: SD2˩6кhܾ+f7ˀX ;=Vއ!-WX.d3İ#hԴ9M} ˎ<t_Io\S1J {fq3nT#ikBBQJGks_# h\uOgjbR\G%WS&6 _>÷rD]H1 *'2iz@ס߲pX':J҃:ШI}m UDzcRDD8'AU`Bk5N.C dVylw I R=5dd]y!\zůϭ((K. A+Xds%dM@&HyQ)Ư] #WߪJZv~ 0uX~!7y|Lh,[LBۂ;6nhX愖V}@jwdl%UӜZ3h}bVL5”W@y{QU^/=QAL^CXm[p4%Oq&I-KsB!sƕӱN%W 9].#O$ /xU jx_RY'H3OL9--MBu1@R$תZkF "<L2FVn0c&4W(mGXayZݪ|,/ih߯ e?d )Q%1OQXzIcől+⦐q(vOȽW^:|GEǾDYD{憖E+BOwsH.THe&2R=i~(\w!(yÔ סIvS. y D `[c3l_uSsƱ>ihWў!Hђ(h,\U*_jA};T+Q< EnE7aUGV.b ShMG7;t G&ICc vB{*Ḓ Ba4 N#6D2x"&^*>d>))b;4ϣ],@٣ Pp[k)0lulR,iey% [oLa90,\=5Q֝~6_tMhï>#oǾ _WW^йi^!$-/my10{ Z)P*M*APhW ۚaH< m?:e SK*˼V9~*ܹ=gi{_*[ubXy~zϿX[~pI?ㄝȨbjSH}o^YAdp % 2x ¸۽h"0=(B\C{E4 %  WvGbz-ф#8yi.JsfpVZw:I#!ݿM=#Fas]&?ORĝxE#dJJфrƐ!P1 ݣvwx Shh0O 裳٧nj`V}xd :Z]|8atm r V]79$/s:]ooa<{X +@I,Cآ"K#,_{dF+*L)(1Rڼ RTp)?*ʌn*/3utmno>X?hw|g}sgy?eOO`Xyzf q[V`ǑXy9 '539Fck;0uݣW E5K+6qX+dA&ͪ"A0m=z@-%h@J:$$ÑK@)9y;#,$NzǕ?Tѭm THkյjoLvJ7+Ǿ&Y P Bm{z 76:6fAE/|`9o6yߡP"(]nVinwz % RSJ&R aTZCD3; :a-F-Jl9 9K=D*)iT YlCOd񗫙gj@5=Y; 7(!GB2,G(GZxo ~?qbɛ O᥹MmoWi-mLօ+sF?P{Wh1>SJS!4]|"Z +E8Пy[ f:&aYVުJFJ-'>nɭmI z 8`P IWtI @l?a@Z? bsJƝrcUZ>°P׹`FЧ`O-[U%Q; Y/d@>ShC7dXL\M5KJZV$d =g0v.g{͹@wC#hI誇^ŋMĎ ygNَ^xm*RIENDB`appstream-generator-0.6.8/test/samples/debian/000077500000000000000000000000001320016272000213435ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/debian/dists/000077500000000000000000000000001320016272000224715ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/debian/dists/chromodoris/000077500000000000000000000000001320016272000250215ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/debian/dists/chromodoris/main/000077500000000000000000000000001320016272000257455ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/debian/dists/chromodoris/main/Contents-amd64.gz000066400000000000000000000216561320016272000310270ustar00rootroot00000000000000jVContents-amd64[6Way]U]$;EY$ CI6%Iʗsx/DRT\<C2RF 72!8+x))uJHR\BȓTJnpIWɡ*ƊU6'K.mz<J%h*d˅,*V6@VHy` $9QDT&NN Z&8 f:@GHJ~[suĖ :mr]ٱ;[׺& n Jr|YqGw B 2sK0cRÂ/?׿|GbЦ>p|`/b-KgK+%7T Cׁk%F!WNɞ0HbIrMÍB"Ҷ>@ eИDzM9/U}baśWU5gr@{nD{HW5>T7h;%0(g U69w;Z;4pR5H֟I@vF=B4!NW_y+\NQ5?*zoKֺSWpLo?|>=,$I-j C  7D-J(ȡN~sBTPF9<8a%ud5 {Ubj2I2=H,czD#7€ 0k6\ -b[z;)qfq@Hk.@A 1SP%~߄'٥%yB`ApśJ #h4䀤A{żu3S䱖2ƉbG'DT˜CQX ^ɥBU#({ۖ4 ᶀ !9XEliʹ*erI ZSO3s5-frސ㶄6߲6X]%g1:! ܥuאqdHQv#pٱhF'i1<:LidEev!H@ RtqIZQPlF01,Y (4-u%ẟ5:$IM *bTnp<\3󅷢,Sf9vV4miG̭WhtIDq4e(rTFL$"\4YI#\/H'rX>Ś% ^mHq|װc&w1Ck V,8~,G9x7U83αhM'{`j[~ :{d8R`ˢ¨{Yo$/W 8+F v!K\nډZRt4RW2 ,'D Nc%AzLοW Q1U*jWh\uqz ƫPy;{)O܏X]dy%6Nc@m+Ӧ7 93CZ2dk\GuZZ \&4GUh.gzt)([ԩ:"3P0|Sae4J"\ j-t5}N8iB~ XN2hTeM2fNC|I[W<$bDm'ŎIG$%:=C0I{~F+|Khp\  Gv{<~xYaBsz{(z.Îֱˮv~ ҄wvN0TQi:AK-j3ͻ<;43v7)pY`uT;ֽEk1UzHWߍ0S1gz/{[dg0rF-Ym$居1cR&dvxTٚYGn3 ~In]M"~i`Q*3L䤂~V"ľJC\`-}Φj2'?,ӪMpp_41x}p@'w P=;,O Trq qI$lʶQS <D`zu,̨>?R 0CUƙY*h-:5~]krͪ 68Ǎ"b5:;j R靨n/Lic4xOU-h$l uD;rJ99Jqc(v-i|(BHAG"PʌV2@kRUהn{}t RCD Z[ {7sfv_Z ESp*.3Zq@4,ؘ21(Vg#p8x+^x>}ﲹ j0jY]uAn tVvP\>a Bk6o)'׵nV@b9Xu/q >b5@)aGZoV3vr75hjQJ>Lh]L/>+/bXg`z:FK`1d[V7vUk"/fR}yz|1pd2}6a?"ǧ?ha&!o?n> G\n>^ne!GCn%ҦmgbzzmҖ2ISŦogB ^%!>% Y9bmy8cO_}L.)r4r@D A#i!e֘ҶG"%,k#' A9BN̏3O/m]~.M!~Ҏ=*HZ|OBɏX'g!;^he]W Șf4=#EG_"׫]iI`hWs aA* :`u*׿N?Fy+Q:zgxN_w H"}kOe?2eG90 PO8@OodkpM쳣6yCe^z~tqV! Ț`S֌.u1F_+6O[}xD@@J,.uBhr$lx-J\P.;Y }i#kuKJȰ7WƂ$8d"H=U)$HF}2>ŞVG@f@ۦ%QX/( t_c Aq uzy(Č؜8oWvVҝ:0EV>SF!u~R\P;>P~m[TjJSH7ToQ]D2C>'RRLA(V43A6m<0ʔ2}qyToPei6xl2dLRJ*N#Bt8VOET OQb MQ 2|]S_I_WB[P (q!mTdP*-LBu9{xSOOoAYZӅ-PKY4e]1Rg,ϑ -SJb(Rڋ̫iIoP<7F3%9DQDqeV>^/9^3Mj\1,4ʏPWM"=8Gj1Nu*smenEMq^aC-}HA}P>efnv\= T+ȕtby29#pW#$>JjL[I%,5/ H YM  fW01ex!m0fɻ^ƘgE& UʥD0+?vK<~%2Rry9T7>.Q⌎ xf6Ҧ1hF?#3=CF'w@?4oD'sgI" )>mk!5 'vߏ0Vc+ a`p>ˊe#.§,+4X=G(1{1߭ݓhѧz)r~;-g>v/?(:dYdqA26vIHPZR*nIA5TVs3"kX85T-;Ttq;pS;NdkOVIT,B7(V ^f_L jxMRK8A(\ؠDa>[Gմ^Rk5n ^r0A`XBknz-2 R"69k0j\49K2%5r#ruTZ|Uv{r| UDcONC"S4yHu&)௜EReMh0wfS11&o_;g='흚+I5Yf@I_[Ŕ%a]δVXY;mۨDIJ 3f:3>Q@&s9@xrJJK\P"Ki>ǚPszlŷZ]H/=REg>|__\*djɍc7wK:֞E@L-Nк?9Gy7R)ޜ(r"n09v )n uGH#[#E 7pp F:yo*h,˭g(] g7 ~7&zєr(aw%՝u 4TVtU"C̦.M) MV9+ޔMo[eraǐ e>g=夞dV<%у"C/ SQZjNsQ+'LOA05=7%a:nBRĕzp6sGgB /1R{QR%V .ġw*!f8RI|td߱@aa`0vتB8yO>[󈦠~ġDq͛;j<%iZRgq ;#ހ YI]HQgģ'"GqG4>+&3(G(Äf XKIt SAi{\;ǎm(}#zRfitZ|HM)щ rE)Aϔ3 1H|z8QoL2B䃘k &?}kc(^S.Tg=8peb Ћ^Ȍ0xNf&?Ok|'^W! -xC>}˻_>5GxJPG{2 ;u0yQe[r/Jb-*Y5GgY{{P6N!ٱcK'lT',p& OdnjKKș5eŻyajec]5S6%X5%27ɩYN1N I1KV2u>H=nŀSBzf7F.~A+955}_ r=a/"P 2D i 3{Kv6*ȚNcnCb4HeCʬ蕖oH&dH3hHA3CEzAeyBs_m8Do/Tf䣴QefO$[ne(rqzu?hzQ)idj@M_A)D{iWbm]0&fAz|* 18:U踙4[u99ڷ7m][ϕUԵDN1LKn0q1~hp123%~h'3@nbzMLp錛e? oswXg߱Zi|`Gm3a]W~B49JpJ9 άCx=A c/0kzn*YQvx\J+b }W,u[bڂƮ;M+QvZ!L&,KN5ϳId)'eΑYwVAvQd[6&Y&Z V&-iVbV$5`֠VsFYʛj8,5=Q+\Avܦ!<3:n%Q/C 4Si^g +<ϲ$R8v6CNؕYdi؍KaYC7NχFQFyZGx/f%yCdB0|1‹GdL̦^*oL uk N!eLmrdž3Y%m[^ݨSFKMrͺGSfpSmwIF9Nd7 l QO@r%ݷb;@4WOMvZ zOєw:]Ufnؾ@ޔ{k/qsappstream-generator-0.6.8/test/samples/debian/dists/chromodoris/main/binary-amd64/000077500000000000000000000000001320016272000301425ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/debian/dists/chromodoris/main/binary-amd64/Packages.gz000066400000000000000000000122461320016272000322270ustar00rootroot00000000000000nVPackagesZێF} +43wAcX ۰ejxIk5,K_1{%{"IVݲbdwU1qD$_J}!7QYն]xX5BzYUքg[,,}v-wWVVa_nm& Z+:U'gmf5gom`?{] Z{îZ6]*ٻݮ^t7uН7mf욶԰ߛmXvF. .7o0U^bZ -4 -g 3i@eU$$p2qc%FTƂ/O+'/2@@K?/7 @ue}T4,ШaB ʶg`yX*@U^pmN||eKUYkl*f([on<<)hΰ`$V%xxCXHU-@$IS=l2f]8*1ʦL02kb[Hp42 ,NF2ܙ\G<"Uj$˕i!tµyHQ)"Wa^ȵÿ%w!(B{W w⃩˛Щr #'a?`9l:x^N7jW+ٝvlO /$$i7AUv sV|C@)aʶ+?|C*W4('U=6 tV15w4+ v3lwd^xc~5a7E)5d5áojހZ]5C#oU#+l;ٰP lGѶ-$(k]  @Y7=o[Ry ?aS:qɠ7OΞC:B$5BmKlBη7okf?K?ξ=?Me>; @]y)#4@Dk}BW@3ECW6TsfeIh\<Ϳ=16ԯ]d?CgD9J!>gOW |PeHoM}87%93#-;Ph|+Cϱڣ-b44.\&^QsYn'ԅ6 8k)fr,c)Jc@;P '5 jZPUGQhPu7Y ^Pi_ayݘ£)vmRLC%9iZyP7'v{8/y;oޏ@1\yZ߉gZRu2ˢ߯U'Kg3Y`dxL_Ƽc<؁ njDy[ueQ‚rDa0ԥ+ kJzX%k|sG|jl˴$PHaL dR7WA;SFmw7;LLhwmAiju&%@%ˁw.@$fg)>\!޽͍V!mC8%|;Tl}l%5rd;}gA< /ĖFX=Dd nZm[KEM |֔}X|zVBkгHn7c~@D4h'>k۴K铙APnƃnebCwͩd#D'Ɉ>=: <9ZB7G;NRvس%xUyQ>["~E8J&p'O}z 'xifɸXu,υq6O9NFuBdFg87RgP -H Al/mAqΤFsĖ)NKkL$cgҡ{~}c|"e; l^0<:dHA%1yes\Ȫ\ίY: їdQ32cLƀЂ bSc י*vq "Lf\0P' 8 5x-y*o^80ʔ.2iKˣYQwQmvжmI}l-߿=%>,E8 s>\$ք;ͻvzE̹CÉLZٕ~Ua^Lz>ƼVoݦ@ʺa$Y[)K fd&U.֦]-"_(gwj6ޕ>3E]S>8[w\h, ;8 qɠj?_Ox;oJKY,"Y* eApTi "#9Q$P̹cG0v:Ӈn0c +GZ8$BU|5/<a?K{&1fQ3#٬<FI*KgbGej`.mٯ qۍnhD1ʫ}hV2M+4X/~lJ}~|,}v+ahw`jX|3hwl=b\p'%Z(-j*`aJ6(7ApMAG(B谔4 ;D9| ]0(JV!F HSd¯oR6~s2| SďT+NIhrh*LZ~ʼnr)]Z@51[C M;c K6*)ꆸ H[`Z赁F!/7appstream-generator-0.6.8/test/samples/debian/dists/sid/000077500000000000000000000000001320016272000232505ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/debian/dists/sid/InRelease000066400000000000000000006306541320016272000250600ustar00rootroot00000000000000-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Origin: Debian Label: Debian Suite: unstable Codename: sid Changelogs: http://metadata.ftp-master.debian.org/changelogs/@CHANGEPATH@_changelog Date: Thu, 28 Jul 2016 09:29:12 UTC Valid-Until: Thu, 04 Aug 2016 09:29:12 UTC Acquire-By-Hash: yes Architectures: amd64 arm64 armel armhf hurd-i386 i386 kfreebsd-amd64 kfreebsd-i386 mips mips64el mipsel powerpc ppc64el s390x Components: main contrib non-free Description: Debian x.y Unstable - Not Released MD5Sum: 76936f00190cab4ae8001838366675c6 1318264 contrib/Contents-amd64 bfef3ff1a24f2458f4aa0daa8db8809a 23860 contrib/Contents-amd64.diff/Index 9bbc070747a7fbb835e1bbd4b28c1efb 101470 contrib/Contents-amd64.gz 45789bdfeebc45e9d3f2393b0457080e 1175578 contrib/Contents-arm64 59ef2e526db59981b2f697376317c89c 18448 contrib/Contents-arm64.diff/Index b585710cb7b529f99babeb018a751995 87797 contrib/Contents-arm64.gz 9616ad3465885d02f89ce99b09c18bad 1177832 contrib/Contents-armel f42265fa148e7beb1f36d8a95185109d 19432 contrib/Contents-armel.diff/Index a74899c8f4800f519ba25c6b5ec9f1a5 88158 contrib/Contents-armel.gz 6e95aa32591033b7a46851f5762215f1 1164602 contrib/Contents-armhf 68f315bf0c2fb1b8f0ea53c92b142d48 19432 contrib/Contents-armhf.diff/Index eb0f7db757ce657c2edc96b9ee8a9d34 87806 contrib/Contents-armhf.gz 38cab633587a72acf54abd8411ef10c0 1103107 contrib/Contents-hurd-i386 9f78d5d835696aca78d83f7516e7bd9f 18940 contrib/Contents-hurd-i386.diff/Index f1362e02cb534fcc7aabc4bce3cb7b0f 80883 contrib/Contents-hurd-i386.gz 12a23604a09cab75c561dc3038349b27 1290908 contrib/Contents-i386 ae9a0202d7b4ef970e9d91156186430b 23368 contrib/Contents-i386.diff/Index 0af8716ba23577cf2bbe7037d8085c28 99126 contrib/Contents-i386.gz 61898d041d0bcb5ea76278ae8ea9b144 1110069 contrib/Contents-kfreebsd-amd64 4907d62cb00264448fd093b647935563 17956 contrib/Contents-kfreebsd-amd64.diff/Index 8aadeee8fa90ac0a634181983f15484f 81795 contrib/Contents-kfreebsd-amd64.gz cac4d7a16d185e4605c8b3af2956ed1d 1109182 contrib/Contents-kfreebsd-i386 e757b31a95be3c13da48be30b24fc861 17464 contrib/Contents-kfreebsd-i386.diff/Index fc3f02dd8748ba208c0178efaa75b1b8 81545 contrib/Contents-kfreebsd-i386.gz a1a09e6b574814d24738516662ebfd28 1159398 contrib/Contents-mips 0936793b8f08ebc300238341e49654c8 19924 contrib/Contents-mips.diff/Index 4b180f2c69ef52d31f541234c7219b2f 86916 contrib/Contents-mips.gz 4d320fb7d8d6c187cc96350df207c435 1151939 contrib/Contents-mips64el 5bc2d41d3ce5ee999616f51f7b5d6346 18940 contrib/Contents-mips64el.diff/Index 8e243ddd024a70102ef0824877d06c93 86243 contrib/Contents-mips64el.gz 99d29dc09a61774dad60f7d69ae98eff 1159421 contrib/Contents-mipsel 8b404ccb477256c402724384a0efd039 19924 contrib/Contents-mipsel.diff/Index a91548dd6caf580f18232f971ffbf021 86916 contrib/Contents-mipsel.gz 4dccbf22e95bb24f37b2467678c11ffb 1180561 contrib/Contents-powerpc ca38e407233736ff497ae81f5409ef5b 18940 contrib/Contents-powerpc.diff/Index 6fb207e6264260bfaad79316a683fe76 88488 contrib/Contents-powerpc.gz f88f3a5246a95ab161511ccdbbffb514 1142562 contrib/Contents-ppc64el b3b4f516282cd659e37a01dd45eb3ec2 18940 contrib/Contents-ppc64el.diff/Index b1114d1d622a1394424d5c80a8f31948 85835 contrib/Contents-ppc64el.gz ac54b385917a98856179ed8dfb914dbc 1155432 contrib/Contents-s390x ad6daa027695744e5429b26045b4af80 19432 contrib/Contents-s390x.diff/Index 71d6f26fcd2323d63c0a84e39eb41dbb 86413 contrib/Contents-s390x.gz 5f21f15aaca421a1beb2727ca531bacd 3519818 contrib/Contents-source 18b82875a5dc6fd42142dcafaf44e798 24352 contrib/Contents-source.diff/Index 95bd86b0649fe75730b7a7c90e09c330 389700 contrib/Contents-source.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-amd64 b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-amd64.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-arm64 b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-arm64.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-armel b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-armel.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-armhf b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-armhf.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-hurd-i386 b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-hurd-i386.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-i386 b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-i386.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-kfreebsd-amd64 b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-kfreebsd-amd64.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-kfreebsd-i386 b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-kfreebsd-i386.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-mips b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-mips.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-mips64el b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-mips64el.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-mipsel b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-mipsel.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-powerpc b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-powerpc.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-ppc64el b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-ppc64el.gz 68292125276158d468c91a58be0f30b1 451 contrib/Contents-udeb-s390x b49002146fad4eb7e4dce23bc3f48e38 271 contrib/Contents-udeb-s390x.gz db07a500b8e2d51a1c6165f7c7d49263 90903 contrib/binary-all/Packages 035ea549e0c204722715991e2c48fd3f 26745 contrib/binary-all/Packages.gz b47817473f85f3dc1166283d6dbb9970 23788 contrib/binary-all/Packages.xz e00258bbbf38227aadbea5bf9f08af11 105 contrib/binary-all/Release cc6ec5981c3a16e2b5f2d5d1c10b83ca 224553 contrib/binary-amd64/Packages cf47005475a2d07a2df1f7e2efad5424 27796 contrib/binary-amd64/Packages.diff/Index 7464e2b4bc1ddd4e6ba5ca25c3bfc987 62636 contrib/binary-amd64/Packages.gz 079d8fff6e0703ed548c1ca2bc772641 52468 contrib/binary-amd64/Packages.xz 465133a3a391b0f6285452fbcc621120 107 contrib/binary-amd64/Release ccee7273456185be5c0f53645145cb5a 173735 contrib/binary-arm64/Packages 69a6ad82fab38b1703abcf309aa7b1b5 27796 contrib/binary-arm64/Packages.diff/Index b4320a9705f7b81ed37cf39813d66091 48846 contrib/binary-arm64/Packages.gz 6e5e7f45a525e9a727c48e7aa049340a 41604 contrib/binary-arm64/Packages.xz 70e72d09cd1216faff1786b186f7b629 107 contrib/binary-arm64/Release e0c8be877cd53deb2ee92c8aff46f475 175162 contrib/binary-armel/Packages 13dda2b297a266f2c19b98abd92dff1d 27796 contrib/binary-armel/Packages.diff/Index 769ebb9f9e23f8cb5238d2b1eb895d17 49399 contrib/binary-armel/Packages.gz 472f6b9e57038c3f4f30f93406c6945b 42060 contrib/binary-armel/Packages.xz d7da68ee268629ac14567afdb9c16075 107 contrib/binary-armel/Release ad63a40a45ff953ec3f62620366b906e 181954 contrib/binary-armhf/Packages ba028858b08e6027e0fabd2e60f90684 27796 contrib/binary-armhf/Packages.diff/Index d0092f2594449140e4f010b088949f16 51101 contrib/binary-armhf/Packages.gz cb8631172db58f6e7f938c3ecf28008b 43400 contrib/binary-armhf/Packages.xz a2cb49824f6ea7e5fc6c3398d93f6c90 107 contrib/binary-armhf/Release 181d8cd4fe1abf6a0348d9cbd600efd2 147251 contrib/binary-hurd-i386/Packages fac098136e0c11301cfe90c102e052e1 27796 contrib/binary-hurd-i386/Packages.diff/Index 1a1e4a66c5ae37926fdd73af40cccac5 42491 contrib/binary-hurd-i386/Packages.gz bd6bb3766b9fbd05b8b9c043ece636a0 36440 contrib/binary-hurd-i386/Packages.xz 5de9e1d5c34c6429e3280c611901acad 111 contrib/binary-hurd-i386/Release 2ebdb99ac445fd1e9772ed59b0c3a4cb 214181 contrib/binary-i386/Packages ce79e3f92870afca25f1df71e4cb8c43 27796 contrib/binary-i386/Packages.diff/Index 5bab9a27ffa70a483e211281259f8b55 59731 contrib/binary-i386/Packages.gz 312215b0ba43ed704660cf713f76181c 50404 contrib/binary-i386/Packages.xz 78512545310e20e1a5269eeec8964b85 106 contrib/binary-i386/Release 1e54f91f258b788190f48119b88c40e2 156547 contrib/binary-kfreebsd-amd64/Packages 5058edabd42c8d7208ddd7f177a06b9b 27796 contrib/binary-kfreebsd-amd64/Packages.diff/Index 23e787dd54c05786365f596682a08405 44496 contrib/binary-kfreebsd-amd64/Packages.gz ea98bda487f9dab96c3807d925bfb143 38132 contrib/binary-kfreebsd-amd64/Packages.xz e50c34bd5f47b30a4bcb86bef7975614 116 contrib/binary-kfreebsd-amd64/Release 9778c40897b37b57ba2924f3e99e8b8a 156427 contrib/binary-kfreebsd-i386/Packages b910c20a6f70cd62fc36b362f30b03c4 27796 contrib/binary-kfreebsd-i386/Packages.diff/Index 8e0cb14dc33a1b37009eb0ff7c9cd5d1 44488 contrib/binary-kfreebsd-i386/Packages.gz 17f02a26c38946428018c8c672c7bbc0 38184 contrib/binary-kfreebsd-i386/Packages.xz 1ca18bf7c94cd46cdaf297567a59bc9e 115 contrib/binary-kfreebsd-i386/Release 0d78956fc1c55b256dfa21c1770f2a9e 173496 contrib/binary-mips/Packages eecc813f58f3b8980415e1483c3a8b87 27796 contrib/binary-mips/Packages.diff/Index a59e89c627cf65d148f2b865c3d31916 48888 contrib/binary-mips/Packages.gz 9b9a41523ca7d7fe2711df2526b43c40 41788 contrib/binary-mips/Packages.xz 96afd38f08284a16cb242eee20402fd1 106 contrib/binary-mips/Release c2023c4785237ff0569511b1be28ac29 167584 contrib/binary-mips64el/Packages c998e06384ea1f1d7c5dc0b9dbb23b94 27796 contrib/binary-mips64el/Packages.diff/Index 1d623dfe80c49e48557457d1978c5aa0 47081 contrib/binary-mips64el/Packages.gz d02dc52e7e1c93be4368546a501dac56 40424 contrib/binary-mips64el/Packages.xz 3b13c342bd7a0607c43a230cc7138790 110 contrib/binary-mips64el/Release 996788368459cd1955bfab1aaacb1f87 173896 contrib/binary-mipsel/Packages 6c763cd323977a5957a4ef90c2ff95de 27796 contrib/binary-mipsel/Packages.diff/Index e7c7f731589e0e4a0a8a5dd612bf80de 49030 contrib/binary-mipsel/Packages.gz ee073d5641887bf4a17420f1674dcee0 41792 contrib/binary-mipsel/Packages.xz 74cf4bae45fc7682a08d6d8f1e6dd760 108 contrib/binary-mipsel/Release 0407fc65942986fc957b1633a28e3768 177845 contrib/binary-powerpc/Packages d2de0ec9f243ed2155323f2e73e7ed62 27796 contrib/binary-powerpc/Packages.diff/Index b5423c69151e767d765fc3e43bf77581 50212 contrib/binary-powerpc/Packages.gz 7d06e3a3ac87ae984bae3a31253e80a3 42644 contrib/binary-powerpc/Packages.xz 14c6768d1b56622a250e90692b59a46d 109 contrib/binary-powerpc/Release 6e8256f750f2c308408e3a0f841de602 172740 contrib/binary-ppc64el/Packages 42e8c4480c8bcb0fddda6e5968b20048 27796 contrib/binary-ppc64el/Packages.diff/Index 39700d0783456519411c94038ab716a6 48549 contrib/binary-ppc64el/Packages.gz 3ee7fd2fb2bfcf64d2d5d90fc14bf9f1 41448 contrib/binary-ppc64el/Packages.xz b90b505d19146c0e066863ea36412c80 109 contrib/binary-ppc64el/Release 0598d44f3e15f67e367aef8789931f9b 170484 contrib/binary-s390x/Packages 2040deb0094389f1179e1477e30727c6 27796 contrib/binary-s390x/Packages.diff/Index 9fda9aad132aacc8049a29d4a56d2153 48250 contrib/binary-s390x/Packages.gz bbed3a3f3ca3e5e7fe1b4a7692bd2a50 41044 contrib/binary-s390x/Packages.xz 3755c075b383fc15a93ab8b29ce641fe 107 contrib/binary-s390x/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-all/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-all/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-all/Packages.xz e00258bbbf38227aadbea5bf9f08af11 105 contrib/debian-installer/binary-all/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-amd64/Packages.xz 465133a3a391b0f6285452fbcc621120 107 contrib/debian-installer/binary-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-arm64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-arm64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-arm64/Packages.xz 70e72d09cd1216faff1786b186f7b629 107 contrib/debian-installer/binary-arm64/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-armel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-armel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-armel/Packages.xz d7da68ee268629ac14567afdb9c16075 107 contrib/debian-installer/binary-armel/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-armhf/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-armhf/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-armhf/Packages.xz a2cb49824f6ea7e5fc6c3398d93f6c90 107 contrib/debian-installer/binary-armhf/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-hurd-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-hurd-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-hurd-i386/Packages.xz 5de9e1d5c34c6429e3280c611901acad 111 contrib/debian-installer/binary-hurd-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-i386/Packages.xz 78512545310e20e1a5269eeec8964b85 106 contrib/debian-installer/binary-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-kfreebsd-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-kfreebsd-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-kfreebsd-amd64/Packages.xz e50c34bd5f47b30a4bcb86bef7975614 116 contrib/debian-installer/binary-kfreebsd-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-kfreebsd-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-kfreebsd-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-kfreebsd-i386/Packages.xz 1ca18bf7c94cd46cdaf297567a59bc9e 115 contrib/debian-installer/binary-kfreebsd-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-mips/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-mips/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-mips/Packages.xz 96afd38f08284a16cb242eee20402fd1 106 contrib/debian-installer/binary-mips/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-mips64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-mips64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-mips64el/Packages.xz 3b13c342bd7a0607c43a230cc7138790 110 contrib/debian-installer/binary-mips64el/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-mipsel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-mipsel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-mipsel/Packages.xz 74cf4bae45fc7682a08d6d8f1e6dd760 108 contrib/debian-installer/binary-mipsel/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-powerpc/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-powerpc/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-powerpc/Packages.xz 14c6768d1b56622a250e90692b59a46d 109 contrib/debian-installer/binary-powerpc/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-ppc64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-ppc64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-ppc64el/Packages.xz b90b505d19146c0e066863ea36412c80 109 contrib/debian-installer/binary-ppc64el/Release d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-s390x/Packages 4a4dd3598707603b3f76a2378a4504aa 20 contrib/debian-installer/binary-s390x/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 contrib/debian-installer/binary-s390x/Packages.xz 3755c075b383fc15a93ab8b29ce641fe 107 contrib/debian-installer/binary-s390x/Release ce92e6dfe91c9390868e0f3e4cf6df8f 37465 contrib/dep11/Components-amd64.yml d47781428f68e71f3320856df3252808 9645 contrib/dep11/Components-amd64.yml.gz 114dbfdc20818ddbb3b17f60ed129161 9052 contrib/dep11/Components-amd64.yml.xz 5fffee3d51fc8b194b027c25c191d163 33085 contrib/dep11/Components-arm64.yml 7156b72fec41d12624350bca57e5fc57 8364 contrib/dep11/Components-arm64.yml.gz 4651beb52d002f94d1871cd2d3614368 7872 contrib/dep11/Components-arm64.yml.xz 0afdc6e63cc65122c28f499028c4a4a9 33085 contrib/dep11/Components-armel.yml 7990e09e3e99d3082030ee26e430ccef 8255 contrib/dep11/Components-armel.yml.gz f833ee70cac40f2a65e99ed857963680 7832 contrib/dep11/Components-armel.yml.xz 464c4a3e1ba350097d8680df4a734435 33085 contrib/dep11/Components-armhf.yml d9211402d4c2964a4fbcc9b2fe652b8c 8344 contrib/dep11/Components-armhf.yml.gz 1db57318262e97a48dba53e17c9c0f8c 7860 contrib/dep11/Components-armhf.yml.xz e3ff4f7307186538b127f37345b07447 37465 contrib/dep11/Components-i386.yml 4a7c9a72f94c91cf233a6c91767e532f 9620 contrib/dep11/Components-i386.yml.gz f50339d2be9d743aac18cf0a05a5e11b 9052 contrib/dep11/Components-i386.yml.xz ad46de43c30f96bb42cd5533e43d173c 31558 contrib/dep11/Components-kfreebsd-amd64.yml d8d82ed4b793161ec52db891285a9a3d 7777 contrib/dep11/Components-kfreebsd-amd64.yml.gz 75dee44d1dcf47a17f1829bc3c795c55 7328 contrib/dep11/Components-kfreebsd-amd64.yml.xz eabf301f181ae921726c9920248d1e7d 33085 contrib/dep11/Components-powerpc.yml 16657094afc59692c45be4125329ec61 8314 contrib/dep11/Components-powerpc.yml.gz aeb166ef90550957bec79ca35c253688 7864 contrib/dep11/Components-powerpc.yml.xz 9bb126b19f2888542a1ae114b7c2a4af 372224 contrib/dep11/icons-128x128.tar 94860c8d9551a0b04c101126043bf69b 304821 contrib/dep11/icons-128x128.tar.gz aa64c0a5409688d71fa34973339bfe3d 160768 contrib/dep11/icons-64x64.tar 20fc54d701f75bdac50deeb8801ad200 120717 contrib/dep11/icons-64x64.tar.gz e0f526a83297781edfcdc5204f1bf866 180882 contrib/i18n/Translation-en 71128f827188b4bb28cbd9847f854650 47717 contrib/i18n/Translation-en.bz2 30db714c4408541408d20dcbdeaccd3f 12544 contrib/i18n/Translation-en.diff/Index 96a1ec18a257b9c5da342e87336af24d 108 contrib/source/Release 360cfdcde53f0ffd9fbef781fc813e71 189731 contrib/source/Sources e31b4abf0a8727194f8f8b485fcb0e9d 27796 contrib/source/Sources.diff/Index 5680a4b1ace341717f497b26d49c0dc2 56034 contrib/source/Sources.gz 18441936c32701b1f4c82fd4fdc8b683 47676 contrib/source/Sources.xz ee316089d76ec1b3157e7e602205706a 486486404 main/Contents-amd64 8736f7d7d3c00865bb699339da3378ac 28024 main/Contents-amd64.diff/Index 1a77b48abd1d53423d2b7d0ae206cde6 33741709 main/Contents-amd64.gz 38db2b28d8fa75e08e4be36d9f34a790 464406406 main/Contents-arm64 d65b379a3c964c199434eb746f3d4ac7 28024 main/Contents-arm64.diff/Index e4ca2a7f4ce99ee7e0ff0c7fe6120c04 32427484 main/Contents-arm64.gz 4a6e2f3be652de4b53fee4ae8fc65cf0 462714353 main/Contents-armel 6d9a1550e947646f09155a9a742cc87f 28024 main/Contents-armel.diff/Index 733848b5a7d4bc790ac4049524a7e93f 32372160 main/Contents-armel.gz 55fbd13d082def8c31a7ebc389e86325 465331124 main/Contents-armhf 774925c7655d72dee4a8cfd62e64b9be 28024 main/Contents-armhf.diff/Index ae9463dba41ea69ccb5367b7eed8d07e 32551542 main/Contents-armhf.gz 6aa25806e19961331001b5ff64b9a014 437011535 main/Contents-hurd-i386 a5be6b90e1eef3659752df9978815a32 28024 main/Contents-hurd-i386.diff/Index 857f0045f8eed012e88c337911fea1c0 30282285 main/Contents-hurd-i386.gz 30364de05bf12a8449cced18c78f2bf7 484515088 main/Contents-i386 3c20ff9867dc54ff8311ae90d2767974 28024 main/Contents-i386.diff/Index 241077710e7229a4f9c43ad795723bfc 33649417 main/Contents-i386.gz 3631d88d325e24fba0a1e9a66e98d3dd 449136892 main/Contents-kfreebsd-amd64 b099938d9f72059efb46676206d19be1 28024 main/Contents-kfreebsd-amd64.diff/Index 607925cb1665ad6e0b98773683d54a36 31341686 main/Contents-kfreebsd-amd64.gz 999ec3b31309d9483b551be3954d6a62 448627460 main/Contents-kfreebsd-i386 3a78f1e5220f291c6817431f9bbeb07c 28024 main/Contents-kfreebsd-i386.diff/Index ca08c72ab78447398cc48592cd8676e8 31305004 main/Contents-kfreebsd-i386.gz 30e37a196f4cee83ed4383411260bfac 460036580 main/Contents-mips 0707bb5adde70601f195ab49bea34deb 28024 main/Contents-mips.diff/Index 935c7cdc3d205ecb98c83b5597f5dca2 32236221 main/Contents-mips.gz 6f55fd9c61da45fd1e8cfbaa299bbf37 459438445 main/Contents-mips64el 1a87ca3ab23d02394c31d57418241818 28024 main/Contents-mips64el.diff/Index 7c6e9beae58cb39db8333a380fd4dd91 32030589 main/Contents-mips64el.gz 44b1854e38e2ed5f1d4b5eea129e4236 465041084 main/Contents-mipsel 93900fb47da7b47c5331a7d9b245bfa2 28024 main/Contents-mipsel.diff/Index e8f93fa8b1d6aaf7b8517c3fb0bdd704 32541643 main/Contents-mipsel.gz 9353556da7ca10327824835fb4e1e5ed 465654055 main/Contents-powerpc de1614badf54805be0c72cf33d0a027d 28024 main/Contents-powerpc.diff/Index e38a7263ce5cb08e96b2bb948fe26f2f 32538984 main/Contents-powerpc.gz e7a2f63c83949133414374616601c1b8 462882892 main/Contents-ppc64el aa12e85431c9315c4468fd333b2b0a1d 28024 main/Contents-ppc64el.diff/Index 50da71c6c8a0ed04f94ea744a3fdd2ae 32352649 main/Contents-ppc64el.gz 09078c37a3aa277346d09df4ded07d2f 459302164 main/Contents-s390x 2d7987fd743413a9e0d42762b186faee 28024 main/Contents-s390x.diff/Index 5d007fb854cad448b0dc980ec96e72b8 32174741 main/Contents-s390x.gz 3f9f3f180230bcb30a731f2fc06b686e 482453699 main/Contents-source 766aeb64fbed4ff551403313689f2b57 28024 main/Contents-source.diff/Index a75c9bc97dfa4fe9434ee525d24251d3 53745770 main/Contents-source.gz 928e37ebff0cfa9ce1618985c5f37dc7 484751 main/Contents-udeb-amd64 a5a9820e853661e0fe8b9aac0cab5958 38535 main/Contents-udeb-amd64.gz 04c87ab2627b88fc32088f66809ad659 419372 main/Contents-udeb-arm64 a6525b449bde4dfcbad07f351eb5f9b3 34115 main/Contents-udeb-arm64.gz a911b6fba961d936169e7ed99a184c59 414623 main/Contents-udeb-armel feb351d9b874d290d516fe4efbb2c539 32491 main/Contents-udeb-armel.gz 757dc43eb85187560e2cbd417fff1786 504043 main/Contents-udeb-armhf d1286fae424148204ce9c8bbb2069120 39965 main/Contents-udeb-armhf.gz 9ab52d365a5f55c411b45f0b6771977b 266208 main/Contents-udeb-hurd-i386 ed815b721e699b73a7a4285820d2f04a 22517 main/Contents-udeb-hurd-i386.gz 953d938f13d70a717cada03b45f2c0d1 710802 main/Contents-udeb-i386 42540645d271e7b3636d0a8f0a76c775 54082 main/Contents-udeb-i386.gz 3219c6cca0fdf4ecef1dbf2767a6acda 289951 main/Contents-udeb-kfreebsd-amd64 76839f660ea6e3850c43b10457e40842 24182 main/Contents-udeb-kfreebsd-amd64.gz c0bc594c1b8d7633eaab1a45b0e7966d 289869 main/Contents-udeb-kfreebsd-i386 f0819488c505e6ff36622bed54c91e1f 24244 main/Contents-udeb-kfreebsd-i386.gz 143a17bbfd91d49c510d64c74917a2e8 577017 main/Contents-udeb-mips 2bb0fd7e0ea134b96b9031c790892353 44213 main/Contents-udeb-mips.gz 9cd61e3907666da87ebde517eb37869e 723583 main/Contents-udeb-mips64el f55c7401a1680861fb8b55a189dd76a9 53323 main/Contents-udeb-mips64el.gz 31ecad337aa42bf23b8a7c198656b32a 1008989 main/Contents-udeb-mipsel 4c47c966560843331329545a4a1505ee 71028 main/Contents-udeb-mipsel.gz a259b0594e077f1ce85e735a8a31532e 583828 main/Contents-udeb-powerpc c00518e1f8b131c0000fc64934b7bc48 43594 main/Contents-udeb-powerpc.gz 9605e715d0da43c2703d028833b1a7c0 396155 main/Contents-udeb-ppc64el 03c887f7e6af3ebd8f8dae91b477b055 31809 main/Contents-udeb-ppc64el.gz e77d64695018da365373e7a7b44134c8 307502 main/Contents-udeb-s390x 327c1a251237ba0ca23db736f54528f6 26131 main/Contents-udeb-s390x.gz 8ade86bbd39832fc327cb974cea3a596 17781690 main/binary-all/Packages 83b43a550aebbf511d73f1efd74e4296 4391664 main/binary-all/Packages.gz ccd2fe9f6c28333f59a81a16ea5330dd 3337812 main/binary-all/Packages.xz 10085e8cf6c39e33baf83b03965074f2 102 main/binary-all/Release 9d15c1d6773cd2a24e580d556a636c8c 39256459 main/binary-amd64/Packages 380e3c0605f49bd1937e96f6e6171fc4 27910 main/binary-amd64/Packages.diff/Index 3bf28cd4699902485fb817afca2521ff 9576288 main/binary-amd64/Packages.gz e65fb137990e2ee6449910bc122bc1d7 7147528 main/binary-amd64/Packages.xz e3a090a211110a1a0fdffc2cc7a1c915 104 main/binary-amd64/Release 8fe0e406851d474ceaf3369468bd41b0 37571520 main/binary-arm64/Packages 60efb4ecdc4242c296ed5889f36706fa 27910 main/binary-arm64/Packages.diff/Index c908fe0fb189cd2de4308fd22a3cc349 9227318 main/binary-arm64/Packages.gz 019e1c8630c4b2174921061629aa0579 6884520 main/binary-arm64/Packages.xz 806d63700dac5cea4d29e6a86e58597d 104 main/binary-arm64/Release 4b36b97c3b0e47a788af02d0d2c7b4d0 37699046 main/binary-armel/Packages dbf57f1b126980bbbd7aa4634f0f164b 27910 main/binary-armel/Packages.diff/Index 2c60d28349f8c6c687fc37287b3d0a0e 9275300 main/binary-armel/Packages.gz ab9ddab168b634af1462f1bb0f5a353b 6921736 main/binary-armel/Packages.xz 5c1866d5f05996c75c2150ae69ad9815 104 main/binary-armel/Release 24762c704bc847754986b33caad4a738 37788052 main/binary-armhf/Packages 55af3c509d618db8d9f61e527d0afdf4 27910 main/binary-armhf/Packages.diff/Index 51ada163986a84e78bebd0b03b558024 9300334 main/binary-armhf/Packages.gz 1299022e3a2b7f332e6b65d20a05f3a0 6934520 main/binary-armhf/Packages.xz 87de7b798ba50f1e06ba3ee7a1db41b4 104 main/binary-armhf/Release 19fc25a37c5921182d993cdf0780b760 33806130 main/binary-hurd-i386/Packages 556b6b5ec18daf59f55191ab6c3b9ef6 27910 main/binary-hurd-i386/Packages.diff/Index d4590d9af46bd2435fedd57ef85c4335 8234995 main/binary-hurd-i386/Packages.gz dca28a9d3407408ca288e32a5adec10b 6163664 main/binary-hurd-i386/Packages.xz a84d93ba0ec25a5d1986ea4fcd76d92a 108 main/binary-hurd-i386/Release c06fa33ebe82447a723cef2af9d11a8e 39044462 main/binary-i386/Packages 3bc70aa8440f0a1caf914d5ac142123f 27910 main/binary-i386/Packages.diff/Index 81501e7c090fe73023f9351b1e02ce85 9548697 main/binary-i386/Packages.gz 910d74a441a289bab8de245237aca84f 7122292 main/binary-i386/Packages.xz cf30be831f54859034d2e11501806247 103 main/binary-i386/Release 47f030c0fa64704d93015f8b6b144bb8 35913320 main/binary-kfreebsd-amd64/Packages 9659e819847108e0e39f9e5e23d6b1d3 27910 main/binary-kfreebsd-amd64/Packages.diff/Index 5ec898199fe93755d1fb64c86e224935 8718641 main/binary-kfreebsd-amd64/Packages.gz 44f38681311cea43878ab21aa70496b8 6512728 main/binary-kfreebsd-amd64/Packages.xz 05d24fbef387f91e082ab5dc7c46b9ee 113 main/binary-kfreebsd-amd64/Release 0e46ca35edca54c68c6fc6fa40cfffc8 35809649 main/binary-kfreebsd-i386/Packages 1cf37e1a15bf701fb58276911deb792e 27910 main/binary-kfreebsd-i386/Packages.diff/Index 83faa3a7b131530d4c1f135facae2bda 8704036 main/binary-kfreebsd-i386/Packages.gz 6789374d0ef709221e9683719bcf21a7 6502680 main/binary-kfreebsd-i386/Packages.xz 262a86cd91b0d0d5fb921a317d76df0e 112 main/binary-kfreebsd-i386/Release 229a406feded170996ebefb13ec08cd3 37366754 main/binary-mips/Packages 53f100c30462cdb18aa9f097c0394d42 27910 main/binary-mips/Packages.diff/Index 3a348375ed9851ae75692a436641ea10 9210212 main/binary-mips/Packages.gz 1c1bc0b691df9cfd5790d2055f648c68 6873512 main/binary-mips/Packages.xz 9d9f639b9f52548b2eb8392e691a5c5e 103 main/binary-mips/Release 5b3a92396132930feb2c5d1afbccac67 37340330 main/binary-mips64el/Packages bf4b6c4f633568da3717a24c9163ef7b 27910 main/binary-mips64el/Packages.diff/Index 67cd956d14111c950b0b0171aaee3a96 9156063 main/binary-mips64el/Packages.gz fc0ee60864c7483d6a8d98a81e2047ad 6834608 main/binary-mips64el/Packages.xz 8246be42dc917113cba664e98bd50d3a 107 main/binary-mips64el/Release 5e364fe4381b0d18d9fa3407a13607c2 37668023 main/binary-mipsel/Packages 7e63b52935765be1f4f8f41bfff932d1 27910 main/binary-mipsel/Packages.diff/Index 93887e92bcede6b341b1f22762b4630b 9262851 main/binary-mipsel/Packages.gz ef3c44197a1b9a1a7ff49d5dbbe52bc7 6912400 main/binary-mipsel/Packages.xz 3dc8b9d46dd15d877218c7c13d0e2884 105 main/binary-mipsel/Release 91ad2fa7d560ad9a114562a6f66d9a00 37823973 main/binary-powerpc/Packages 97fcc2b38b44cd0f1a6f1055adc8b8b6 27910 main/binary-powerpc/Packages.diff/Index 8aa5805ab669d80b7174f37beab2061b 9292207 main/binary-powerpc/Packages.gz 99602114bee93a0f56d25dc4f8add0a2 6929276 main/binary-powerpc/Packages.xz 066a5dd8d4763961ca7e72ab118e91d4 106 main/binary-powerpc/Release dbcd9dca16846ab516d809d1fe9c6d3d 37859587 main/binary-ppc64el/Packages 07322d6518dd19ac2e177e1bba7aa39f 27910 main/binary-ppc64el/Packages.diff/Index 1ab9453951f0af4d9c4f19bb6a0b7ccc 9277244 main/binary-ppc64el/Packages.gz 03d1d9b800de33125a75f75e59ecde60 6921148 main/binary-ppc64el/Packages.xz cc8afb9a3d24cea535c031ff83cc1bdf 106 main/binary-ppc64el/Release 6f03bcfea77b6b05e5959c9a48e0736c 37432240 main/binary-s390x/Packages 1d2a46185ed0bb161ae606673816e2b8 27910 main/binary-s390x/Packages.diff/Index 55b2873204d740bb61d1fef7c44f3a9b 9217612 main/binary-s390x/Packages.gz c04e71c9af4f85a3cb3572a47bfb6b02 6875604 main/binary-s390x/Packages.xz 8644bd20faff93a0b7716ca2e987ed96 104 main/binary-s390x/Release 1f772f7b647e73ad65bd8244ccf6606c 63066 main/debian-installer/binary-all/Packages c53b106eab1021074e41b465e7d7cf93 16829 main/debian-installer/binary-all/Packages.gz cde4986c79280dae866d3ac5893cf58b 14836 main/debian-installer/binary-all/Packages.xz 10085e8cf6c39e33baf83b03965074f2 102 main/debian-installer/binary-all/Release 5c134da0018d86ecfa464c17fd4c4807 258901 main/debian-installer/binary-amd64/Packages ff7d6e3aef8ad0d2606f498b9b9b312d 65129 main/debian-installer/binary-amd64/Packages.gz 0a0d7f601780e2e9e251bf77b95835cc 54808 main/debian-installer/binary-amd64/Packages.xz e3a090a211110a1a0fdffc2cc7a1c915 104 main/debian-installer/binary-amd64/Release 7f27f4fd16c5a61495f79920c2b69152 239565 main/debian-installer/binary-arm64/Packages 803a71ee6cb342142e7cab22d068bfaf 61678 main/debian-installer/binary-arm64/Packages.gz a536ce6e1d687a3c14dc6368d9edac6a 52152 main/debian-installer/binary-arm64/Packages.xz 806d63700dac5cea4d29e6a86e58597d 104 main/debian-installer/binary-arm64/Release 0c2f83d7603e1a94a75bb0fb55c2db5e 277695 main/debian-installer/binary-armel/Packages 759db9003daa3771dc6f7df2378654fe 67415 main/debian-installer/binary-armel/Packages.gz 9d496d50885bda800a9b28b082317616 56652 main/debian-installer/binary-armel/Packages.xz 5c1866d5f05996c75c2150ae69ad9815 104 main/debian-installer/binary-armel/Release 216554fdcabdecf7396d03436278a2d8 238490 main/debian-installer/binary-armhf/Packages 412f4ece6f0a6415e671b9ae6f3a5d2e 61449 main/debian-installer/binary-armhf/Packages.gz a65b1e027e43be059b0595a99661577e 51968 main/debian-installer/binary-armhf/Packages.xz 87de7b798ba50f1e06ba3ee7a1db41b4 104 main/debian-installer/binary-armhf/Release 46aebcdbbbfb439976bdf6cbab8cb1c4 163351 main/debian-installer/binary-hurd-i386/Packages d2c999206c127e2756b1fef9bca78460 44433 main/debian-installer/binary-hurd-i386/Packages.gz c53a434fd94adb1f01102945896b018a 37804 main/debian-installer/binary-hurd-i386/Packages.xz a84d93ba0ec25a5d1986ea4fcd76d92a 108 main/debian-installer/binary-hurd-i386/Release fae19170644abeb877ef7cb7fefa8389 326037 main/debian-installer/binary-i386/Packages cb6eb5aa7994ec1603e7b7dfa40eac2d 75140 main/debian-installer/binary-i386/Packages.gz 175c0a257d4384a9920d870c0a887b52 63056 main/debian-installer/binary-i386/Packages.xz cf30be831f54859034d2e11501806247 103 main/debian-installer/binary-i386/Release 31edeb172d84f67e53565e513f72d5ac 199536 main/debian-installer/binary-kfreebsd-amd64/Packages 996c98fcf568bb706df7f12b74d591cb 52052 main/debian-installer/binary-kfreebsd-amd64/Packages.gz b69fe29f33ef0f127075501561e02c04 44020 main/debian-installer/binary-kfreebsd-amd64/Packages.xz 05d24fbef387f91e082ab5dc7c46b9ee 113 main/debian-installer/binary-kfreebsd-amd64/Release d8c67469af6a623d0378a0a77260e952 198799 main/debian-installer/binary-kfreebsd-i386/Packages 12cefc0c7ad5d9485c3f1210e95320ac 51848 main/debian-installer/binary-kfreebsd-i386/Packages.gz ba7940166304e6d4c9226cbf083bcac6 43944 main/debian-installer/binary-kfreebsd-i386/Packages.xz 262a86cd91b0d0d5fb921a317d76df0e 112 main/debian-installer/binary-kfreebsd-i386/Release cd6ba1715c8dd3206a1db6d760aaaf65 299343 main/debian-installer/binary-mips/Packages ecca0c469dc3f398c41cecb551fac41e 70317 main/debian-installer/binary-mips/Packages.gz f97068d8c284bfb47af9b1f762ee9291 59428 main/debian-installer/binary-mips/Packages.xz 9d9f639b9f52548b2eb8392e691a5c5e 103 main/debian-installer/binary-mips/Release cf3dbee9b700902fe4067509874623f8 360842 main/debian-installer/binary-mips64el/Packages cc4a7d0dbb5eac93e698c021eae9f686 78622 main/debian-installer/binary-mips64el/Packages.gz a716d07ad9d6abcf990fd8dfd2c7e344 66228 main/debian-installer/binary-mips64el/Packages.xz 8246be42dc917113cba664e98bd50d3a 107 main/debian-installer/binary-mips64el/Release ace3200c84545df887a44de51ff45a3d 479718 main/debian-installer/binary-mipsel/Packages f2fe95f520fbacc0e344551e1ac6dc60 94984 main/debian-installer/binary-mipsel/Packages.gz 962396873962d1c525397b9d1c1cb238 80008 main/debian-installer/binary-mipsel/Packages.xz 3dc8b9d46dd15d877218c7c13d0e2884 105 main/debian-installer/binary-mipsel/Release dbc98c4149ed3bd0887dc8ebe14877ba 310055 main/debian-installer/binary-powerpc/Packages 57bc261239119875a729b73d9e95b181 72594 main/debian-installer/binary-powerpc/Packages.gz ef0d4217eaab3d6dfee94503a6e7bd35 60748 main/debian-installer/binary-powerpc/Packages.xz 066a5dd8d4763961ca7e72ab118e91d4 106 main/debian-installer/binary-powerpc/Release 31198895a526db6c434912f95566a0fb 241368 main/debian-installer/binary-ppc64el/Packages 0f77f3afb0bcbbf78b4352f870bcdf06 61537 main/debian-installer/binary-ppc64el/Packages.gz 793f00c0010c2ce15f474450f61c7da6 51868 main/debian-installer/binary-ppc64el/Packages.xz cc8afb9a3d24cea535c031ff83cc1bdf 106 main/debian-installer/binary-ppc64el/Release 61441145bd99af408307e3aba37da10e 217996 main/debian-installer/binary-s390x/Packages 911f2e61806f7487700cfcdda189c0ef 58135 main/debian-installer/binary-s390x/Packages.gz 97393e1d43b85a370b055cabfb4c2fad 48892 main/debian-installer/binary-s390x/Packages.xz 8644bd20faff93a0b7716ca2e987ed96 104 main/debian-installer/binary-s390x/Release 1be16ae9bcaa4d71ad54aefa158d0741 7796441 main/dep11/Components-amd64.yml 732f1040515480d9e43b70640103b84b 2854073 main/dep11/Components-amd64.yml.gz c6698a2a0283112674726e53f7fab4ab 1850876 main/dep11/Components-amd64.yml.xz 3d0a7cb0fb243858415b8f7101380071 7735559 main/dep11/Components-arm64.yml a9591dd40c9ca0eea351ddd652da8e53 2835371 main/dep11/Components-arm64.yml.gz 0c8465b31304d95dc287c570f8ddf0ef 1839368 main/dep11/Components-arm64.yml.xz eacbffae318216658b9a18add435a6d2 7744621 main/dep11/Components-armel.yml fdfe5bbb75136248ff776fbd3c7b7934 2837621 main/dep11/Components-armel.yml.gz 160860e7053cb47167c651525b52e39c 1840304 main/dep11/Components-armel.yml.xz 6a8923dce0d3d21ce7a089a69e2e2608 7753412 main/dep11/Components-armhf.yml f0c4edf897f8ca8cc93f7201173a4ca4 2838544 main/dep11/Components-armhf.yml.gz 980acfd0a92bff12bcdd7b83515bc70f 1842132 main/dep11/Components-armhf.yml.xz 37d3152322d44bdf96bdc19da2f8405b 7795011 main/dep11/Components-i386.yml f24043ea4e83a25f76d67e533004a2f1 2853321 main/dep11/Components-i386.yml.gz 54ae9c7371b0593b99e935684b61e4b9 1850760 main/dep11/Components-i386.yml.xz 55ba75bfecfa1fd5cbb1fd4f97dcbe1d 7285280 main/dep11/Components-kfreebsd-amd64.yml 5788f902e8bc2b33ea5800bf4e0b876b 2669347 main/dep11/Components-kfreebsd-amd64.yml.gz 578df9dbc63281664eedea849e60631c 1732772 main/dep11/Components-kfreebsd-amd64.yml.xz 46df1c219af20dd2c1951903df5e7eed 7747672 main/dep11/Components-powerpc.yml 242ab1e62e0bea1e80dbade25f2d2df1 2838839 main/dep11/Components-powerpc.yml.gz 4f980e4a58d23d7f732989dcf796303f 1841208 main/dep11/Components-powerpc.yml.xz e52bdd59f2f7dbbcb176a4f0a43f16b9 17068032 main/dep11/icons-128x128.tar c9efbb8a8005e19429ad2e15a76f04a2 15132129 main/dep11/icons-128x128.tar.gz 650e62ecc56676b2f445b7bbdf2f9b1b 8170496 main/dep11/icons-64x64.tar f643dd47e28d5a08c5f8f688c16596e9 6466066 main/dep11/icons-64x64.tar.gz 0071a785652b9a6f6c7d1dbec292a25c 8628 main/i18n/Translation-ca cab00f4af70523ecdbf645e7f7ee2492 3543 main/i18n/Translation-ca.bz2 c1961e8d860a293b033a6a975ca17c68 1755527 main/i18n/Translation-cs af72078ec1a260d5778aa99c2354e8e9 456958 main/i18n/Translation-cs.bz2 ca359d40eb141112515e2bc9f2032f08 14512 main/i18n/Translation-cs.diff/Index e6aa62edfced0fd7ac54da06eb6deefd 17190796 main/i18n/Translation-da 7a484c530f3ca3dcf5f5b45c0ea270fa 3716728 main/i18n/Translation-da.bz2 fe455625cace78a9bd4494b0d67aac04 27910 main/i18n/Translation-da.diff/Index d3b62a232514714ef632dcafb4df1989 7563488 main/i18n/Translation-de 0cf191dd8ca9aebfefe0034fc720dfd3 1724541 main/i18n/Translation-de.bz2 86e70b7b43dadbfc6cb932293268ecd8 27304 main/i18n/Translation-de.diff/Index a344219bf0eec9139d5270017ecfceee 1347 main/i18n/Translation-de_DE 0fe0725f74bb5249f15f30ce965142d5 830 main/i18n/Translation-de_DE.bz2 c26d1f5d454d59a734435115a463bc5e 8287 main/i18n/Translation-el a2e3d718b49885932660c9c5dbdc0570 1896 main/i18n/Translation-el.bz2 b5e6c14f747fd3d3ea480e4b0fdcb597 27076273 main/i18n/Translation-en 7cd099961072cc7a1a685d18f8b1c84b 5427424 main/i18n/Translation-en.bz2 8248703cda79af6d6df64ebcb607cf90 27910 main/i18n/Translation-en.diff/Index b38a08cc72a01f896fa745a25ef55c00 2517 main/i18n/Translation-eo 82bf9de0303a2ff3fb791f19c84f3c25 1279 main/i18n/Translation-eo.bz2 745a93b46c684078c290249362cdcf30 1326503 main/i18n/Translation-es 691f4e9949f6a13c01b0dc016015bdd3 323379 main/i18n/Translation-es.bz2 bf1ae7fcdadb3150158681852b8117fa 17464 main/i18n/Translation-es.diff/Index fe1a2c966238e27a62bc1d9531978927 14383 main/i18n/Translation-eu c2dc13f9f8a39978e10ae070437a5362 5475 main/i18n/Translation-eu.bz2 a894e9b1a8c56b927d37fc606a2d92fd 736 main/i18n/Translation-eu.diff/Index 48d0c6ee8c241ea6335713ce281e0980 386506 main/i18n/Translation-fi 798db04510751ffa53c3848205b95efd 106618 main/i18n/Translation-fi.bz2 0678f7e2ee77b76f2866b47c88713a03 11068 main/i18n/Translation-fi.diff/Index acf5e6f0027a3756ad32b596aec21793 7401641 main/i18n/Translation-fr 26d9074edbb798bbd1b4837a5343a772 1518856 main/i18n/Translation-fr.bz2 f00d9eeb8f2cc8e344fb76e071fabec1 27796 main/i18n/Translation-fr.diff/Index 54790b326f496d11042e7afa4c4631b1 21899 main/i18n/Translation-hr 9fdbf9e07c96ee5af56030d154ff607f 5692 main/i18n/Translation-hr.bz2 cabf65aab935b431ac8030167ef8eeef 2212 main/i18n/Translation-hr.diff/Index cc423bce94fd7d062ec63881438d6373 96810 main/i18n/Translation-hu e1205e9042cd5be51989f5b4533aa8a6 31851 main/i18n/Translation-hu.bz2 4119e3b251dda916b184607c8514ec78 1720 main/i18n/Translation-hu.diff/Index cb9bfeca0fea2c93ecccdc320b485294 7124 main/i18n/Translation-id d0624bdc42d2602cb4664b190e372468 2899 main/i18n/Translation-id.bz2 2381f089c05c4e0ac6cb5c8ffd600b2d 21789753 main/i18n/Translation-it fdc75537379d05d4bed7acd588b01f1f 4268806 main/i18n/Translation-it.bz2 6cccac8e38b9357ff436204a1a084056 27910 main/i18n/Translation-it.diff/Index 64697acfcd63339ba56af18a4de28a08 5075815 main/i18n/Translation-ja 0bbc55ae9583df8ff28b694b60640a83 913629 main/i18n/Translation-ja.bz2 2045762863e31cddc9166a4e80a84b62 27304 main/i18n/Translation-ja.diff/Index f6fe5be7465cd63813c244b1a1f54c45 19077 main/i18n/Translation-km 17c60ce8f72b68982629b2e469915109 3407 main/i18n/Translation-km.bz2 12087f416d16de7c5ffd6698a9dedb0f 1720 main/i18n/Translation-km.diff/Index f375c313c1e93832540f1e2f47f503bd 1631004 main/i18n/Translation-ko dd61eca2bc9adc13f33cf80f106713d6 348522 main/i18n/Translation-ko.bz2 c8d9248d7a963c2b5aa9bda9b1fa7599 22876 main/i18n/Translation-ko.diff/Index d41d8cd98f00b204e9800998ecf8427e 0 main/i18n/Translation-ml 4059d198768f9f8dc9372dc1c54bc3c3 14 main/i18n/Translation-ml.bz2 5676b1dbf1afed1dfd2ed8c4d87d6f8e 2325 main/i18n/Translation-nb be1e645de35839db0778d87b8e903e43 1302 main/i18n/Translation-nb.bz2 92a2666c8a09bb4cb4fd0649a87adf99 264671 main/i18n/Translation-nl 0b2c46361ecfdeb5025a5cd67f3beb89 71487 main/i18n/Translation-nl.bz2 6c0270d045ed66a981290e1a31177f35 9100 main/i18n/Translation-nl.diff/Index 70503f8efbcb3ab4092ab5198c5d78df 2458040 main/i18n/Translation-pl b6e413762a2dc3b79dc0f7ea6e27802c 569778 main/i18n/Translation-pl.bz2 3d7080de3027e28aa20808e3248a077c 26812 main/i18n/Translation-pl.diff/Index e7a1a2f02d37eaafc8a23437aad0a43a 1564381 main/i18n/Translation-pt 55e4c007261255a9991e72546fd4a3ba 386197 main/i18n/Translation-pt.bz2 2222e20f5c51815f96e3062e0b1d9d25 15988 main/i18n/Translation-pt.diff/Index 3febc6212a82148533ece34ba3012a46 3548094 main/i18n/Translation-pt_BR ed8e05782286ae5b37940b23bb305d72 846754 main/i18n/Translation-pt_BR.bz2 5cfd36393ef4c067d78f7ca3d948a0fa 26812 main/i18n/Translation-pt_BR.diff/Index 60f08a8c65af4e8895cf8c53d1e35b98 2710 main/i18n/Translation-ro a998260e0995f073174d9e0d1fb65a9f 1374 main/i18n/Translation-ro.bz2 b0c2a9c949dcc75045cb71e66a08912c 2655478 main/i18n/Translation-ru ff4a328011b0ff8aad87691a86d220b7 431543 main/i18n/Translation-ru.bz2 9c0448669aac690b8fc06ff2cbff4bad 21400 main/i18n/Translation-ru.diff/Index 88d33ae4bd81a0727d8dce11de7273d7 3819007 main/i18n/Translation-sk 6f2322531d7839e2a27ca48dd65e767a 843783 main/i18n/Translation-sk.bz2 1b4fb1d9ea9d7e58ea738aa8e498a737 27796 main/i18n/Translation-sk.diff/Index 3f7669405e04d1862d6eb8e6817724d5 441964 main/i18n/Translation-sr aa1268bd55a5b92f37682ac36f8cbc78 78350 main/i18n/Translation-sr.bz2 34509802078a71613ebd27a1c42ddc14 8608 main/i18n/Translation-sr.diff/Index 2e7e17ccaed45a46635480f54b65ab39 117165 main/i18n/Translation-sv 20113f96e4db968fa1ad21398e563477 36066 main/i18n/Translation-sv.bz2 1fb32f3ac643d745064a5fdea2152a7a 3196 main/i18n/Translation-sv.diff/Index 617fcb26803e9b2a60c2716ea4744451 902 main/i18n/Translation-tr 96c9deb10e4bb691e778589dec582fd7 530 main/i18n/Translation-tr.bz2 f352a71d97747abb0b7ec10b17df6fed 4277439 main/i18n/Translation-uk 46389306c392dacc4ba9a57a03899c06 669553 main/i18n/Translation-uk.bz2 62b32c0ed3d5609f449841b550306847 22384 main/i18n/Translation-uk.diff/Index 3490920ca94901031bfef0b0179c4530 30443 main/i18n/Translation-vi 4b9f8610634f77136a0ff15daaa2e206 8837 main/i18n/Translation-vi.bz2 31d75bce045815aa393d2275c1e536d7 2212 main/i18n/Translation-vi.diff/Index 7717fa25bd691ec385bddacf42419c9f 2799 main/i18n/Translation-zh b5a4e7e47da47ac7596ed5d72fdeef93 1526 main/i18n/Translation-zh.bz2 cbdf4b385a9e472b4ec44142a2dd6c37 334563 main/i18n/Translation-zh_CN d76c54843dbd3f0e47c236bfc42d8f79 92636 main/i18n/Translation-zh_CN.bz2 145978f6e98c3cb6ff3d37ab5358cb41 7132 main/i18n/Translation-zh_CN.diff/Index 591bd2e425d8755cd1af8b449070ef3e 57122 main/i18n/Translation-zh_TW d565663e6a0417f70b1e1eecd2f0b3eb 20289 main/i18n/Translation-zh_TW.bz2 0bd805f62422f7ee5a4d8cc0f0b59e01 3196 main/i18n/Translation-zh_TW.diff/Index c06312d27a05b395a5a45ae7c2507ab5 53815 main/installer-amd64/20150422/images/MD5SUMS bc3feb487bafcbdfd06e06284000e368 72131 main/installer-amd64/20150422/images/SHA256SUMS 7f129f18d483d8678691e32bb6954436 53815 main/installer-amd64/20150718/images/MD5SUMS b7cab70bdf269ab34b0a5b0d36ec0734 72131 main/installer-amd64/20150718/images/SHA256SUMS 68f30bd7c1f371b82a894837a1643ab9 53815 main/installer-amd64/20150813/images/MD5SUMS 1b9cd6c615f7d0ee59aeee91e089cc7f 72131 main/installer-amd64/20150813/images/SHA256SUMS dcd4a129eb03d7b79764465d97468658 53635 main/installer-amd64/20150828/images/MD5SUMS 7da4e9a6338cbda2de43afefc75ee2f9 71887 main/installer-amd64/20150828/images/SHA256SUMS 515b783412be83349fc94cbcc41f3983 53635 main/installer-amd64/20150911/images/MD5SUMS 30ed9399e20e911c5046120fa65026ca 71887 main/installer-amd64/20150911/images/SHA256SUMS 1f897dfc4d7ae54c3a9d8df23bb7c314 53727 main/installer-amd64/20151023/images/MD5SUMS 6d2f81899356555e441421d51dc741e8 72011 main/installer-amd64/20151023/images/SHA256SUMS c9583f4597e52933689397d09d890d80 53635 main/installer-amd64/20160101/images/MD5SUMS a45f291d4f5c4128e9014271c7b12c7c 71887 main/installer-amd64/20160101/images/SHA256SUMS d6d4aa83312ae55d273bd8385f16aa38 53727 main/installer-amd64/20160106/images/MD5SUMS ab78bc26828b883a79bc9cc23b1286a9 72011 main/installer-amd64/20160106/images/SHA256SUMS bb47b77e4f3d80c9bf892a9d4dd4f8ba 53727 main/installer-amd64/20160516+b1/images/MD5SUMS 421bc2a824adecce9d2376963eb9b63d 72011 main/installer-amd64/20160516+b1/images/SHA256SUMS e4f3a21784d6a3102a130ba20e92f0d8 53727 main/installer-amd64/20160516/images/MD5SUMS 1a3e7aaf715ce42b17cfb6360b16e236 72011 main/installer-amd64/20160516/images/SHA256SUMS b0d1c9a722a2b5affd29b77b902e3a0c 53727 main/installer-amd64/20160630/images/MD5SUMS ce41b2fa73adf559477b37a65d4ead20 72011 main/installer-amd64/20160630/images/SHA256SUMS b0d1c9a722a2b5affd29b77b902e3a0c 53727 main/installer-amd64/current/images/MD5SUMS ce41b2fa73adf559477b37a65d4ead20 72011 main/installer-amd64/current/images/SHA256SUMS c52390d4695c984028c98a32f7a76dff 19148 main/installer-arm64/20150422/images/MD5SUMS f4160f9f0b4b49d8997ee2c920004594 25912 main/installer-arm64/20150422/images/SHA256SUMS 8bb2134b1f6eb311047621b8327b92ce 19221 main/installer-arm64/20150718/images/MD5SUMS 00212197e96943527cd7d877599c1f26 26017 main/installer-arm64/20150718/images/SHA256SUMS 7a76d85513a26f4d247d12f07169a483 19221 main/installer-arm64/20150813/images/MD5SUMS b9582e565c71f9803f145308d626fb58 26017 main/installer-arm64/20150813/images/SHA256SUMS 46aa54cf6adecef384915e9e97139b08 19221 main/installer-arm64/20150828/images/MD5SUMS fc369331103d7c5128e55907b8a65dfc 26017 main/installer-arm64/20150828/images/SHA256SUMS 792e4f72b73996159ba8c760cf005fc5 19221 main/installer-arm64/20150911/images/MD5SUMS 0a85072cf979aa24d6e95e9a2fd05682 26017 main/installer-arm64/20150911/images/SHA256SUMS bbd9976457d3354a20702dc3837a501c 19366 main/installer-arm64/20151023/images/MD5SUMS 3c0d447a3310c59b52634d2536f28dc2 26226 main/installer-arm64/20151023/images/SHA256SUMS 1e7d8258b04971e32b2a1eaaf03f1cb7 19366 main/installer-arm64/20160101/images/MD5SUMS 16a6252eeac87cec2a8a63d5aa643882 26226 main/installer-arm64/20160101/images/SHA256SUMS 81694c96c2c2a89af5094dd5cc62ae43 19366 main/installer-arm64/20160106/images/MD5SUMS 50eb4893fcb29fa5e101ad3d89e16a68 26226 main/installer-arm64/20160106/images/SHA256SUMS a27a3ca9b9201d08a6959c203abd6665 19788 main/installer-arm64/20160516+b1/images/MD5SUMS 24d396d0e93b2f1b994015a7b17b80c0 26840 main/installer-arm64/20160516+b1/images/SHA256SUMS 530f897d2f040bb2171355b978ce3ce5 19788 main/installer-arm64/20160516/images/MD5SUMS b7ff35aeda772a129d9ed692546d0a44 26840 main/installer-arm64/20160516/images/SHA256SUMS 7801f2f68870b7629876cefe1b876644 20520 main/installer-arm64/20160630/images/MD5SUMS 154af14e29eff0e06367dbdb7f319479 27892 main/installer-arm64/20160630/images/SHA256SUMS 7801f2f68870b7629876cefe1b876644 20520 main/installer-arm64/current/images/MD5SUMS 154af14e29eff0e06367dbdb7f319479 27892 main/installer-arm64/current/images/SHA256SUMS 42fdeb26bb11aeba2b73bb665394ed5d 8985 main/installer-armel/20150422/images/MD5SUMS 5508c992d754756a76d94459694d0846 12645 main/installer-armel/20150422/images/SHA256SUMS 68f868a28043100a893c564b0faae3da 10136 main/installer-armel/20150718/images/MD5SUMS af69eb139df5e30ef86e8e9959e82cf6 14244 main/installer-armel/20150718/images/SHA256SUMS 01e076ec44be1c77c251d7d5fc1c9ebc 10214 main/installer-armel/20150813/images/MD5SUMS 652fce61997776934cc902891dfbef34 14354 main/installer-armel/20150813/images/SHA256SUMS 1fe56992ad57188f6c64ef4a587fca08 10214 main/installer-armel/20150828/images/MD5SUMS 2e1860e17b51a02ab3dcd4a6ca2b8270 14354 main/installer-armel/20150828/images/SHA256SUMS ab92cc7d8af85dcbdfeb1c23a1a4ada3 10214 main/installer-armel/20150911/images/MD5SUMS 81239b7aeb188258c05bcd148ba6aca7 14354 main/installer-armel/20150911/images/SHA256SUMS d1ef8153db55b4c7fefea9b5d665268b 10214 main/installer-armel/20151023/images/MD5SUMS 685702eda13193131532e737ac847225 14354 main/installer-armel/20151023/images/SHA256SUMS 907bdf89e1cd0b04c3ea3c5ac5293524 11320 main/installer-armel/20160101/images/MD5SUMS a174d2d7c9f86588e9e6dbd64c1fe95b 15908 main/installer-armel/20160101/images/SHA256SUMS 4d091ea335e1cc28c501fac36f834e73 11320 main/installer-armel/20160106/images/MD5SUMS 303a7bf2d68e0ee414803a694a692871 15908 main/installer-armel/20160106/images/SHA256SUMS b9a3925fa4cc3d6746f3091037410b46 21918 main/installer-armel/20160516+b1/images/MD5SUMS 1cecfbd15243177f6811e81cd44c0fb2 30634 main/installer-armel/20160516+b1/images/SHA256SUMS e2a460d19a1987783987245a64c82843 21918 main/installer-armel/20160516/images/MD5SUMS 985f5387499527325e845ddc5a97207b 30634 main/installer-armel/20160516/images/SHA256SUMS eaf0a967e3ddddbf271a22eb172a253d 22683 main/installer-armel/20160630/images/MD5SUMS db333669e2bc24baf7b5edf891dd2df6 31687 main/installer-armel/20160630/images/SHA256SUMS eaf0a967e3ddddbf271a22eb172a253d 22683 main/installer-armel/current/images/MD5SUMS db333669e2bc24baf7b5edf891dd2df6 31687 main/installer-armel/current/images/SHA256SUMS 77d9da266c887d99f50e4a78770da16a 19599 main/installer-armhf/20150422/images/MD5SUMS e1ea97c8e0f0ab02e0acf66302b64072 28379 main/installer-armhf/20150422/images/SHA256SUMS 084e58bfd24c832bf0518b2087ef57f9 21631 main/installer-armhf/20150718/images/MD5SUMS d331ede290678323e8b2c2ee8b64c1eb 31339 main/installer-armhf/20150718/images/SHA256SUMS fd95ab71c8125b6393c95a658b1c4208 21993 main/installer-armhf/20150813/images/MD5SUMS 53b5644ab2d2dceb5a1aa76a29646520 31861 main/installer-armhf/20150813/images/SHA256SUMS 91a3bb58bdb3f081fd69ee0e5e64d7c5 21993 main/installer-armhf/20150828/images/MD5SUMS d76f6202ffae6064a7e5d8d91b746cdf 31861 main/installer-armhf/20150828/images/SHA256SUMS 6743052cfa5856911fadfec7d185b3a7 21993 main/installer-armhf/20150911/images/MD5SUMS aac8a16428226be115dc66569c3462fa 31861 main/installer-armhf/20150911/images/SHA256SUMS 9af75cfdb021ecfe4ca81d83ade7c198 23951 main/installer-armhf/20151023/images/MD5SUMS a48ab9a8bc1bf849804ffc53eb06e768 34683 main/installer-armhf/20151023/images/SHA256SUMS e25a9a21c87af432d1de665392121307 25780 main/installer-armhf/20160101/images/MD5SUMS 008a0740f85cd184a7da076dc416a0a0 37312 main/installer-armhf/20160101/images/SHA256SUMS ca01103d2b6f761a26d2c1e54d504a80 25780 main/installer-armhf/20160106/images/MD5SUMS 4acd1721546591fcab76797c815826fc 37312 main/installer-armhf/20160106/images/SHA256SUMS 904c6dc5f2981eca165615bf4f5e903e 32094 main/installer-armhf/20160516+b1/images/MD5SUMS 0398c7bcc09de0655cca935474d7b114 46346 main/installer-armhf/20160516+b1/images/SHA256SUMS f435648778a72cc5758610cdd56ac726 32094 main/installer-armhf/20160516/images/MD5SUMS 497beeebd06717cdac51210460acea86 46346 main/installer-armhf/20160516/images/SHA256SUMS b70948b0dd60cec7390d2a38b8124eae 33942 main/installer-armhf/20160630/images/MD5SUMS 69e0668080dd6865f9410c93e2ab58a5 49026 main/installer-armhf/20160630/images/SHA256SUMS b70948b0dd60cec7390d2a38b8124eae 33942 main/installer-armhf/current/images/MD5SUMS 69e0668080dd6865f9410c93e2ab58a5 49026 main/installer-armhf/current/images/SHA256SUMS 6945a44a20596ed6e81e3dea9c2f3ddf 52495 main/installer-i386/20150422/images/MD5SUMS 34ce5cc3c7b4ac330eb592aa8fb8c41e 70875 main/installer-i386/20150422/images/SHA256SUMS 1c5cc19000791e5d93bc7ffe81108eff 52495 main/installer-i386/20150718/images/MD5SUMS a0e176faa0be4cae8d8aeb3103e69b87 70875 main/installer-i386/20150718/images/SHA256SUMS 8047fd41b6469d046c4319e96a25b948 52495 main/installer-i386/20150813/images/MD5SUMS 0203c7fa623222c0de479518d7e164b1 70875 main/installer-i386/20150813/images/SHA256SUMS 7997f898ef1496cb221aebfe5c461988 52317 main/installer-i386/20150828/images/MD5SUMS 9f784e11d66674a93f119cacbc279b28 70633 main/installer-i386/20150828/images/SHA256SUMS ffe9b11bcae11587bc3923ec6523bfe6 52317 main/installer-i386/20150911/images/MD5SUMS 838890aa65f653db9ef53aea88a1582f 70633 main/installer-i386/20150911/images/SHA256SUMS 4bc3cc82cd40a2f863a1566ee59b868d 52317 main/installer-i386/20151023/images/MD5SUMS 0a41ec2e6856567d4356bda25cbda097 70633 main/installer-i386/20151023/images/SHA256SUMS 68cafe55e10bac36cfad4a57c47a89ad 52317 main/installer-i386/20160101/images/MD5SUMS 461c856624885a1979aea49ac3fd9f2d 70633 main/installer-i386/20160101/images/SHA256SUMS 0ba0a658a6f4e044805d79ae12618636 52317 main/installer-i386/20160106/images/MD5SUMS 6526fc3c4bc794aa1d005b26cf1e8dc3 70633 main/installer-i386/20160106/images/SHA256SUMS 1e77990145c4df025f08354f9c35dad5 52317 main/installer-i386/20160516+b1/images/MD5SUMS 76d42cd927e94ca61cc2e019efaaf897 70633 main/installer-i386/20160516+b1/images/SHA256SUMS 883125e6b492a708d24da1be02c8c34f 52317 main/installer-i386/20160516/images/MD5SUMS d9397411580ac3f3036df6faf381aff2 70633 main/installer-i386/20160516/images/SHA256SUMS 996eba6a5d82e580efa86b1ddd8bc6cb 52317 main/installer-i386/20160630/images/MD5SUMS 111ce06fba5d621871d271dbe4f3b514 70633 main/installer-i386/20160630/images/SHA256SUMS 996eba6a5d82e580efa86b1ddd8bc6cb 52317 main/installer-i386/current/images/MD5SUMS 111ce06fba5d621871d271dbe4f3b514 70633 main/installer-i386/current/images/SHA256SUMS d318581f7a29594cc02e0dfacb2dbfe8 2147 main/installer-kfreebsd-amd64/20150422/images/MD5SUMS 97b2421e3bde5da15598d1aa3ce795c3 3183 main/installer-kfreebsd-amd64/20150422/images/SHA256SUMS d318581f7a29594cc02e0dfacb2dbfe8 2147 main/installer-kfreebsd-amd64/current/images/MD5SUMS 97b2421e3bde5da15598d1aa3ce795c3 3183 main/installer-kfreebsd-amd64/current/images/SHA256SUMS 02c599b2311ccde70340e801d33e8483 1209 main/installer-kfreebsd-i386/20150422/images/MD5SUMS 9d81e3c19d2c88f0d3ca2cb0e06e3123 1861 main/installer-kfreebsd-i386/20150422/images/SHA256SUMS 02c599b2311ccde70340e801d33e8483 1209 main/installer-kfreebsd-i386/current/images/MD5SUMS 9d81e3c19d2c88f0d3ca2cb0e06e3123 1861 main/installer-kfreebsd-i386/current/images/SHA256SUMS 48639d5b34148741df2132cb9079bd79 940 main/installer-mips/20150422/images/MD5SUMS e592333fd6d054e559d15027b9c3ebaa 1496 main/installer-mips/20150422/images/SHA256SUMS 224d0f46f32a094f7a42295de8bc1039 937 main/installer-mips/20150718/images/MD5SUMS 55ce95ed5bbd19b1a93c8233fb5269bc 1493 main/installer-mips/20150718/images/SHA256SUMS 92be92e017b485e49883407faeee2994 937 main/installer-mips/20150813/images/MD5SUMS 71732fb124d12d18d2818285d5750cfb 1493 main/installer-mips/20150813/images/SHA256SUMS 7067906c661fbf1aa6aff1b1e3b84006 413 main/installer-mips/20150828/images/MD5SUMS 34285cf66d7d6f7ddc6eb60ec3ecf454 713 main/installer-mips/20150828/images/SHA256SUMS c2eecb82d870fab4132fb5ed53d55d05 413 main/installer-mips/20150911/images/MD5SUMS 42a45de7b7382c3be754544c384a7217 713 main/installer-mips/20150911/images/SHA256SUMS 27c4bd02410bbe9bb7ad681fe0965af1 413 main/installer-mips/20151023/images/MD5SUMS 5e0a2b483d487d151f938cc2d4a827bb 713 main/installer-mips/20151023/images/SHA256SUMS be8382a52df21fc4828ea0cd16d3e6b5 413 main/installer-mips/20160101/images/MD5SUMS 22da8c160c210653e42a34f097e94a41 713 main/installer-mips/20160101/images/SHA256SUMS f36092c5a0f5a57252aabee5235ed957 413 main/installer-mips/20160106/images/MD5SUMS ce69ee304af61fdfb6c72890929c0bbf 713 main/installer-mips/20160106/images/SHA256SUMS 419d3e461777185fd5f1dd0a098d828a 413 main/installer-mips/20160516+b1/images/MD5SUMS 042f2834caa5d1dac12d59ba54261d3d 713 main/installer-mips/20160516+b1/images/SHA256SUMS 2347e235966b2ef3d2e5a64a090a7664 413 main/installer-mips/20160516/images/MD5SUMS 83d65a4470a7bb99c20e77e542936677 713 main/installer-mips/20160516/images/SHA256SUMS ed29a35844345b187504a5b9bbd7f042 413 main/installer-mips/20160630/images/MD5SUMS a21668b1da7ae41d6be97169d2a89dd8 713 main/installer-mips/20160630/images/SHA256SUMS ed29a35844345b187504a5b9bbd7f042 413 main/installer-mips/current/images/MD5SUMS a21668b1da7ae41d6be97169d2a89dd8 713 main/installer-mips/current/images/SHA256SUMS a1c3f76716993801388b8224d75b0968 1213 main/installer-mipsel/20150422/images/MD5SUMS 266b1b098b295678ad04fba1e9734dd1 1865 main/installer-mipsel/20150422/images/SHA256SUMS 067b78e650973a61d0fc05c7789a8c16 1208 main/installer-mipsel/20150718/images/MD5SUMS 731af366b19b62a0dd2cfe33e74ce5a6 1860 main/installer-mipsel/20150718/images/SHA256SUMS 68bdb7f12ffc64f0491605bd33ef2ec2 1208 main/installer-mipsel/20150813/images/MD5SUMS 4f5951aaa4bd36dd4c6b4ecdf63f305a 1860 main/installer-mipsel/20150813/images/SHA256SUMS 144356eb6a59b11efefeccc0bd4c7f46 919 main/installer-mipsel/20150828/images/MD5SUMS d8b729cfd672eeb091b6ceb40f447123 1443 main/installer-mipsel/20150828/images/SHA256SUMS 4f178f3b0a49b9d640ef93e26bf37d0b 919 main/installer-mipsel/20150911/images/MD5SUMS 78afc840fd1494ac4245a4b533a21f6d 1443 main/installer-mipsel/20150911/images/SHA256SUMS cd31221bc19cfb52dcedbc984d153c0d 919 main/installer-mipsel/20151023/images/MD5SUMS c957ab7846cfa747a98815ba700fb33a 1443 main/installer-mipsel/20151023/images/SHA256SUMS 20ddf497b0b8ab7bab70762b17d43327 919 main/installer-mipsel/20160101/images/MD5SUMS 87aee614424b805f75fac5a08020c6a8 1443 main/installer-mipsel/20160101/images/SHA256SUMS d479dae7d216bbce0ebe88e7ef28e83f 919 main/installer-mipsel/20160106/images/MD5SUMS eea0cdfa9fa9463281705b81bb046243 1443 main/installer-mipsel/20160106/images/SHA256SUMS 96f526d410c28b3d5654677835ec32b7 919 main/installer-mipsel/20160516+b1/images/MD5SUMS c9b4ec898f63605d0b3e78c0aa3af1b6 1443 main/installer-mipsel/20160516+b1/images/SHA256SUMS 384596ffdee88d68205697cf6f294b6c 919 main/installer-mipsel/20160516/images/MD5SUMS cad28dcdc8c7b000aec4acb11bb00393 1443 main/installer-mipsel/20160516/images/SHA256SUMS 6e45f9890334ddd5952cbc9f66ff6b70 624 main/installer-mipsel/20160630/images/MD5SUMS d45a277d7403f1a21eb246a6508c294b 1020 main/installer-mipsel/20160630/images/SHA256SUMS 6e45f9890334ddd5952cbc9f66ff6b70 624 main/installer-mipsel/current/images/MD5SUMS d45a277d7403f1a21eb246a6508c294b 1020 main/installer-mipsel/current/images/SHA256SUMS 757a78a03000d563e55139d067fd3463 2128 main/installer-powerpc/20150422/images/MD5SUMS 76c2a153bd1076a232bf969c35155903 3292 main/installer-powerpc/20150422/images/SHA256SUMS 5245865eb003d4be1ed33fd642905b6f 2128 main/installer-powerpc/20150718/images/MD5SUMS 8c9ccd5536735c8f7b991c30fed75674 3292 main/installer-powerpc/20150718/images/SHA256SUMS 0580bccea0f11c44e1d57157a47aeec0 2128 main/installer-powerpc/20150813/images/MD5SUMS bdd024d098d697461fa4a96b4aebb945 3292 main/installer-powerpc/20150813/images/SHA256SUMS a4f9a02bd66f89fde4b88bc0082dde84 2128 main/installer-powerpc/20150828/images/MD5SUMS d33c3fa9fd6cc09f73ac64358d1adbbf 3292 main/installer-powerpc/20150828/images/SHA256SUMS 29a9a229be7ce7813f1c8302c8ba2cb6 2128 main/installer-powerpc/20150911/images/MD5SUMS d949aadd330e8b09cb867b28aeaa0e7a 3292 main/installer-powerpc/20150911/images/SHA256SUMS abd509be91d2158ff0670bc5a7a0949f 2128 main/installer-powerpc/20151023/images/MD5SUMS 708146f02bef4cc752e99c3859fdb95f 3292 main/installer-powerpc/20151023/images/SHA256SUMS 9ca3081166b7b2d71224257ca41007a0 2128 main/installer-powerpc/20160101/images/MD5SUMS 0085cdcca6703fdb838d06fb2cf1a42f 3292 main/installer-powerpc/20160101/images/SHA256SUMS 92cd6aec3ece889809e885dfc4669c0a 2128 main/installer-powerpc/20160106/images/MD5SUMS 1655af9c8bda75e0f89b5af81469e7fd 3292 main/installer-powerpc/20160106/images/SHA256SUMS 07e9f60a46fd4937ec6c4a7202476998 2128 main/installer-powerpc/20160516+b1/images/MD5SUMS 908bd1aa3a7fcc3904add5938081fab9 3292 main/installer-powerpc/20160516+b1/images/SHA256SUMS c4340ecd280d5db8de64db0d767e9622 2128 main/installer-powerpc/20160516/images/MD5SUMS 0f97c9252b9fb5b3c02e362b9c16d21d 3292 main/installer-powerpc/20160516/images/SHA256SUMS c8f9568908e8704b30440ce52da1ebbb 2128 main/installer-powerpc/20160630/images/MD5SUMS adb7777418ccc4e4427274ed251b7856 3292 main/installer-powerpc/20160630/images/SHA256SUMS c8f9568908e8704b30440ce52da1ebbb 2128 main/installer-powerpc/current/images/MD5SUMS adb7777418ccc4e4427274ed251b7856 3292 main/installer-powerpc/current/images/SHA256SUMS 6730181232434b5e0b07f070e4037e5b 576 main/installer-ppc64el/20150422/images/MD5SUMS 6b13d9e4427cf78bdd9a3b70ac84ff0b 972 main/installer-ppc64el/20150422/images/SHA256SUMS 595ceae6c00d35e395a3af5c655c851b 576 main/installer-ppc64el/20150718/images/MD5SUMS 9ab151980e2dd5c500a833a0a341f70e 972 main/installer-ppc64el/20150718/images/SHA256SUMS 8a5cd37d58b4647c5613e7091678a55b 576 main/installer-ppc64el/20150813/images/MD5SUMS 471ec1ca07a0feebb528f874886340c0 972 main/installer-ppc64el/20150813/images/SHA256SUMS cd63cf1e35d8ac047a67802e5dcc9cef 576 main/installer-ppc64el/20150828/images/MD5SUMS ab4431025e32c4dc83cfa311da161eaa 972 main/installer-ppc64el/20150828/images/SHA256SUMS d653d80f04396e2da59447fda908c5f7 576 main/installer-ppc64el/20150911/images/MD5SUMS 85c4644ecd578fb3ba95002dadb441c0 972 main/installer-ppc64el/20150911/images/SHA256SUMS 928c032d7073c4fb5104c1d56da6a289 576 main/installer-ppc64el/20151023/images/MD5SUMS ff02d742114719e31bfb2ad1be3970f9 972 main/installer-ppc64el/20151023/images/SHA256SUMS 6be90a72534881c30ecd59f457276204 576 main/installer-ppc64el/20160101/images/MD5SUMS 98cbf26c82a1e4406ffac22a08269b13 972 main/installer-ppc64el/20160101/images/SHA256SUMS 7b8cbfee46550eea6b2438af6ef94026 576 main/installer-ppc64el/20160106/images/MD5SUMS 701189655541d16f1218ca97f41285ac 972 main/installer-ppc64el/20160106/images/SHA256SUMS af797e06df9a57856950f7d67d4f5368 576 main/installer-ppc64el/20160516+b1/images/MD5SUMS 0a5d484587f0adb492df4b1812af9ca1 972 main/installer-ppc64el/20160516+b1/images/SHA256SUMS e89c504b16aad9e473dcb8cc3f4fbd8a 576 main/installer-ppc64el/20160516/images/MD5SUMS bce4e7471038aeba7ef43ebf15dfe7b7 972 main/installer-ppc64el/20160516/images/SHA256SUMS 2189eb589afec2cd0f0cd91089900aa5 576 main/installer-ppc64el/20160630/images/MD5SUMS d69e675fb6cd05e602bc48a5d687cd2a 972 main/installer-ppc64el/20160630/images/SHA256SUMS 2189eb589afec2cd0f0cd91089900aa5 576 main/installer-ppc64el/current/images/MD5SUMS d69e675fb6cd05e602bc48a5d687cd2a 972 main/installer-ppc64el/current/images/SHA256SUMS 9a80df21f5bd9c52f25e424e490f97bb 374 main/installer-s390x/20150422/images/MD5SUMS 20355389634104504def0522c0a4f62c 674 main/installer-s390x/20150422/images/SHA256SUMS 4e0e1ede661ac15ee62558ffc11ddec6 374 main/installer-s390x/20150718/images/MD5SUMS 4a3f0ba0fa11852a16356a02d7c65d61 674 main/installer-s390x/20150718/images/SHA256SUMS b7b0380dbafde0465b236bbefc97b084 374 main/installer-s390x/20150813/images/MD5SUMS a04317d84c2090c0b0a1000fcc6343f9 674 main/installer-s390x/20150813/images/SHA256SUMS 380794fd117148bc3e26705fe2e389dd 374 main/installer-s390x/20150828/images/MD5SUMS 21f3ba7fe04d79569e6a077c5c374553 674 main/installer-s390x/20150828/images/SHA256SUMS 31e504890d163f03b21abb6082a37de1 374 main/installer-s390x/20150911/images/MD5SUMS 6d3d1016f5df0e95773ce708b70f7bc8 674 main/installer-s390x/20150911/images/SHA256SUMS 1e2bb4157cdf43ad7f176cd58d756f1d 374 main/installer-s390x/20151023/images/MD5SUMS c0b251bb4720835ce2f25f38585f24f1 674 main/installer-s390x/20151023/images/SHA256SUMS 0ee1d4c8c85e7850d2b9c1ccf49ae5d0 374 main/installer-s390x/20160101/images/MD5SUMS 40f55c378fe0761416e3052c0db33d1f 674 main/installer-s390x/20160101/images/SHA256SUMS c1fdd09c06b8f99bf1ea705af74a11d6 374 main/installer-s390x/20160106/images/MD5SUMS 23323a568afe8645e589e5fbc4ba2e1c 674 main/installer-s390x/20160106/images/SHA256SUMS e2beb798b9b891099fe05138e6980b41 374 main/installer-s390x/20160516+b1/images/MD5SUMS 21b59fa9b484d049a30cabcc75a3556b 674 main/installer-s390x/20160516+b1/images/SHA256SUMS fe8310a09e76c93b7d32a13639efe7e0 374 main/installer-s390x/20160516/images/MD5SUMS 524f09e9c4e8910eecdb146d3de7d754 674 main/installer-s390x/20160516/images/SHA256SUMS 2355c08000e7e86685cb6c032aa38ce9 374 main/installer-s390x/20160630/images/MD5SUMS eea708fab440fdf7bce3182abe6b1376 674 main/installer-s390x/20160630/images/SHA256SUMS 2355c08000e7e86685cb6c032aa38ce9 374 main/installer-s390x/current/images/MD5SUMS eea708fab440fdf7bce3182abe6b1376 674 main/installer-s390x/current/images/SHA256SUMS 1ead3b3d8b3cb4ffb20a960556cf6df0 105 main/source/Release 0e7952ec17b7235b111d7a5016032b47 35489733 main/source/Sources f52c0103811638eb1388eeb351af4243 27910 main/source/Sources.diff/Index fa83d0a187aac7405285e3cd33aa197b 9072408 main/source/Sources.gz c64e879844fc7c8cd30f88347aae8635 6901228 main/source/Sources.xz 58aafa7955bc6322b4f57c7f5b5c3018 14518404 non-free/Contents-amd64 990b6c32148ca37b7c7aa07eb2949f1f 27416 non-free/Contents-amd64.diff/Index 6cb38c97f16f34a79db97b2bfb936a1f 812504 non-free/Contents-amd64.gz 9a08d553e6aebddee752270c37349262 13465086 non-free/Contents-arm64 f4b9c3bbbbcf805bff50e5b8f22a16e4 19512 non-free/Contents-arm64.diff/Index d1aff0dd8d4fe3a55e06387756ab0c40 731747 non-free/Contents-arm64.gz 9f70f37064a74691ff5851349343d6e7 13478582 non-free/Contents-armel 2a253ee5195c2b122c0174d3050af2de 20500 non-free/Contents-armel.diff/Index 406c5fc71cd9b16c600d88aeef6f9a43 733675 non-free/Contents-armel.gz 7f0fec44ed7dfcfe2964771b2c83525c 13539201 non-free/Contents-armhf 0a3241cb8687807a8d077340af4be04b 22476 non-free/Contents-armhf.diff/Index e7ce03d12d6ae7d25f839a034595d22a 738525 non-free/Contents-armhf.gz 4f7d7a89369a9c286e286859c0fe471b 13374121 non-free/Contents-hurd-i386 c0de361dd201bfdb7ade8971076089fb 19018 non-free/Contents-hurd-i386.diff/Index 7e6b1db1e79f35ee2be131075cb57ad4 724269 non-free/Contents-hurd-i386.gz 4e5031961c48943298aab229cc67a8c1 13755254 non-free/Contents-i386 7cd295a19aeb292d1990feed2f842d43 23464 non-free/Contents-i386.diff/Index 609a7efdd18a827fa1ee767a89da9814 757556 non-free/Contents-i386.gz 428bc6e6ca1470d39fee62c2766edd2c 13514206 non-free/Contents-kfreebsd-amd64 b022ca3c67d39f53aba5d5d5b2f31e24 19018 non-free/Contents-kfreebsd-amd64.diff/Index 9b7d361f085bfa524f03fef26692fd37 736421 non-free/Contents-kfreebsd-amd64.gz 7846ef7bc79eacff2f07ab2472b558f5 13515299 non-free/Contents-kfreebsd-i386 d839f9e53bb550ed6138f70147c856d7 19018 non-free/Contents-kfreebsd-i386.diff/Index 7b8e46a5df5e075cd606c818dd1455db 736493 non-free/Contents-kfreebsd-i386.gz a1a52318fa404fe3d51aef8281bff12b 13468449 non-free/Contents-mips e86bdef249071f965d7134d5b1e417e0 19512 non-free/Contents-mips.diff/Index 3df62209f599304456ee8665c92e0c8d 732565 non-free/Contents-mips.gz 9d3241068cc75b8480b457a51854f897 13465548 non-free/Contents-mips64el bcd527f4cf51d2aac5e8f647267b35b3 18030 non-free/Contents-mips64el.diff/Index 34703e3fbd05080c4ed72c0b99773997 731477 non-free/Contents-mips64el.gz 0fb464e5128d6bd4173a678ef5bd6c64 13479076 non-free/Contents-mipsel 4acb6639264d35253ca940fed332e59c 19512 non-free/Contents-mipsel.diff/Index cc0dc451b315c016022bdfd04b540a14 733446 non-free/Contents-mipsel.gz 6f430fbb40d213488eb2cfdadb17ade8 13467317 non-free/Contents-powerpc 489d298e3b7044f82a7f1ff0d074c131 19512 non-free/Contents-powerpc.diff/Index 07a79847ad475e8570bbb5575171bfa9 732439 non-free/Contents-powerpc.gz 72740ef0a54bf294ec73677123334a44 14067773 non-free/Contents-ppc64el 8eac145ea2dc0966125d183c8613444f 19512 non-free/Contents-ppc64el.diff/Index a953fc4a17cd0c0023c20a69638492eb 774292 non-free/Contents-ppc64el.gz 2866dc930f991ecc6cd4af049a220445 13475399 non-free/Contents-s390x f12a646b4a8c57277da1ce1a8db96ed4 20006 non-free/Contents-s390x.diff/Index 291d364ee21cee9216bd7a2f1bdf51a9 733090 non-free/Contents-s390x.gz ce45d44323ceffdbca768c2f4f25f1b0 8203337 non-free/Contents-source e1fdae378171cb5f64c6d0128d5e70f5 27796 non-free/Contents-source.diff/Index 27a2aeaebcfde059706aa256c2ae8398 878132 non-free/Contents-source.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-amd64 b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-amd64.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-arm64 b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-arm64.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-armel b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-armel.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-armhf b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-armhf.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-hurd-i386 b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-hurd-i386.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-i386 b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-i386.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-kfreebsd-amd64 b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-kfreebsd-amd64.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-kfreebsd-i386 b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-kfreebsd-i386.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-mips b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-mips.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-mips64el b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-mips64el.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-mipsel b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-mipsel.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-powerpc b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-powerpc.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-ppc64el b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-ppc64el.gz 68292125276158d468c91a58be0f30b1 451 non-free/Contents-udeb-s390x b49002146fad4eb7e4dce23bc3f48e38 271 non-free/Contents-udeb-s390x.gz a4fced351b7a9ee638a35475019f373d 194055 non-free/binary-all/Packages 84ef1554bd13e4f7265586ae3cc2a1d1 52716 non-free/binary-all/Packages.gz 1e890bc84314e880a30769b446b66e21 44872 non-free/binary-all/Packages.xz 6b4250a4eecedfd2aa185a72c35e068d 106 non-free/binary-all/Release 703be0e6bda36aa7ca226d1349c9a18b 372384 non-free/binary-amd64/Packages 07b6b19ff9fab45b2f68311fa15d051e 27796 non-free/binary-amd64/Packages.diff/Index 6d16aece55e77beb6cba6a6f0b947c09 94091 non-free/binary-amd64/Packages.gz debdd06bf579c3fb42f85f7b4268d164 78516 non-free/binary-amd64/Packages.xz 51280d23e2848a2f94270b448880dc07 108 non-free/binary-amd64/Release 602432a5f5800c8fedf44dddcbb4f2ea 228434 non-free/binary-arm64/Packages da7a4a3d93a2e9d496b20e89c327e07f 27796 non-free/binary-arm64/Packages.diff/Index 2b9040d3ce03ca155b25f3ab3e4839b6 62112 non-free/binary-arm64/Packages.gz e5452aaea83dcb29a2c5693811836e1a 52564 non-free/binary-arm64/Packages.xz 283b50d104942e828ae94f7d33cb2881 108 non-free/binary-arm64/Release 4810004f68789de4392cb741faf9bf07 235109 non-free/binary-armel/Packages 33b93ad35bf0dafb6775d54b97807b92 27796 non-free/binary-armel/Packages.diff/Index 59aea2b46f5b236f240c3f2130efaade 64174 non-free/binary-armel/Packages.gz bf1146a16f5f61261f082461b2cd28c5 54144 non-free/binary-armel/Packages.xz c3554a3861dcf3fc787aea5e23f1f059 108 non-free/binary-armel/Release 7dcb40c3bc6c3ba6fe9561b245720641 275515 non-free/binary-armhf/Packages 7429fff5c9e6d55007de8443a5505b94 27796 non-free/binary-armhf/Packages.diff/Index b529a99048903f1df03794f226c15330 71048 non-free/binary-armhf/Packages.gz a484a8e5281b93ded782820358054bbf 59664 non-free/binary-armhf/Packages.xz 994fe90c27992fac81995cd3fcc71d1d 108 non-free/binary-armhf/Release b89850fe04095051eef6fc2af4fd3db1 232894 non-free/binary-hurd-i386/Packages 661a10c10925b1352dcf45418639be97 27796 non-free/binary-hurd-i386/Packages.diff/Index ce78986f71d2a59a4f468bdb414060a0 62661 non-free/binary-hurd-i386/Packages.gz 6e420d06c496326aaca1d86c1f3fbe59 53192 non-free/binary-hurd-i386/Packages.xz f982a54eecaaff5105fc67afbd737441 112 non-free/binary-hurd-i386/Release 44b55f5cd7d84bfff6966d982b42ccdc 337604 non-free/binary-i386/Packages 6b86b3eb6dbde16ec7bd882061c73e73 27796 non-free/binary-i386/Packages.diff/Index 647a330e6b06b7702ba7c93e46ca07b0 85001 non-free/binary-i386/Packages.gz 9ea96c26fc6fda3d4e162e654a8d73e4 70972 non-free/binary-i386/Packages.xz fa526d0f76b842e864dd98295084bf1b 107 non-free/binary-i386/Release d3c299bbc70d6c7c38bf9df17344bc44 238159 non-free/binary-kfreebsd-amd64/Packages e552627a9086ad5fee01012a55bac259 27796 non-free/binary-kfreebsd-amd64/Packages.diff/Index 6389516ec9a9860892fadab427aae47b 64110 non-free/binary-kfreebsd-amd64/Packages.gz 1e9b5c2b716a5d5d1793e7383237ca8f 54172 non-free/binary-kfreebsd-amd64/Packages.xz 589a0d6328a246508c14362fffa65259 117 non-free/binary-kfreebsd-amd64/Release 91f9c8e8222d29ce84c653b11a5a56fe 238774 non-free/binary-kfreebsd-i386/Packages 69cdeb202295c8d3ec9c35f88edf4085 27796 non-free/binary-kfreebsd-i386/Packages.diff/Index 3aa0ba33f1579d5ff39de8e62dbcd7fb 64166 non-free/binary-kfreebsd-i386/Packages.gz 2465604b8cb9d3242db3c36b3be09488 54388 non-free/binary-kfreebsd-i386/Packages.xz 0b463c3a00fe3ebd875dd7795faabe17 116 non-free/binary-kfreebsd-i386/Release ac2f4e224e6abc968526cfb3f7ac32fd 232072 non-free/binary-mips/Packages 91842a9c9b311fae669060f8ba37c0fe 27796 non-free/binary-mips/Packages.diff/Index 8e3883d86f2e273c0f4489f74b95af7f 62918 non-free/binary-mips/Packages.gz 2134132b120ed581a67a235276292886 53340 non-free/binary-mips/Packages.xz a5146fc4bacdd167cc7be86231e52b89 107 non-free/binary-mips/Release 9e385da97ab1c5a0577f14e88de5e43b 229428 non-free/binary-mips64el/Packages d9e178b926025e57fb1f2347357c4416 27796 non-free/binary-mips64el/Packages.diff/Index f3afc71b380945324c27680c2522978e 62084 non-free/binary-mips64el/Packages.gz dd3217bfdcd0fad42a134b059c64b538 52544 non-free/binary-mips64el/Packages.xz 21b7cbdd20ea26dd83b31d8c3842f895 111 non-free/binary-mips64el/Release d953db2519456105ed385d3ff8ed71ce 235706 non-free/binary-mipsel/Packages 247cd4912fef0b89161407eb4b89b682 27796 non-free/binary-mipsel/Packages.diff/Index 4bf19d62515ac650088f10e64a7b5022 63921 non-free/binary-mipsel/Packages.gz 7233cb9bfec2c71e83cf1db246f09ba5 54036 non-free/binary-mipsel/Packages.xz 0f7da028e5005e5d19386284091a326e 109 non-free/binary-mipsel/Release 79f8939746dbdc7617efa22ff06d83da 231104 non-free/binary-powerpc/Packages 5377a7223ece6f27a3916ccf14c52d9d 27796 non-free/binary-powerpc/Packages.diff/Index e09d405b7aea1d80e0dbe97da2b01849 62821 non-free/binary-powerpc/Packages.gz 838370756a541c617efd97d5237652af 53196 non-free/binary-powerpc/Packages.xz 3c481bd491603b28ccef0dc33accdeac 110 non-free/binary-powerpc/Release 6fe1371819def349a4f6d6dad6309eb3 255982 non-free/binary-ppc64el/Packages ad8ded9ddda4f792725ed70e6cf77dd4 27796 non-free/binary-ppc64el/Packages.diff/Index f7e5fed4fce50cb61338d0218bac83fd 68178 non-free/binary-ppc64el/Packages.gz 640207f938532cdfcc19a3b12d587c2c 57476 non-free/binary-ppc64el/Packages.xz d4aed8973b2fdb4ebe2539a352911330 110 non-free/binary-ppc64el/Release cccf31ccee4d9552ff84ef1168890b2b 232449 non-free/binary-s390x/Packages 44b46d2a337dd0a2975fd5dd877c88cd 27796 non-free/binary-s390x/Packages.diff/Index fcf0c878aa0e389ca495d118f4df3383 63088 non-free/binary-s390x/Packages.gz eef11937550a01455d59b2b0fc465ee1 53436 non-free/binary-s390x/Packages.xz e7ceeb59c6faba0761d4bec329d3d26d 108 non-free/binary-s390x/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-all/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-all/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-all/Packages.xz 6b4250a4eecedfd2aa185a72c35e068d 106 non-free/debian-installer/binary-all/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-amd64/Packages.xz 51280d23e2848a2f94270b448880dc07 108 non-free/debian-installer/binary-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-arm64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-arm64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-arm64/Packages.xz 283b50d104942e828ae94f7d33cb2881 108 non-free/debian-installer/binary-arm64/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-armel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-armel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-armel/Packages.xz c3554a3861dcf3fc787aea5e23f1f059 108 non-free/debian-installer/binary-armel/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-armhf/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-armhf/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-armhf/Packages.xz 994fe90c27992fac81995cd3fcc71d1d 108 non-free/debian-installer/binary-armhf/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-hurd-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-hurd-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-hurd-i386/Packages.xz f982a54eecaaff5105fc67afbd737441 112 non-free/debian-installer/binary-hurd-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-i386/Packages.xz fa526d0f76b842e864dd98295084bf1b 107 non-free/debian-installer/binary-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-kfreebsd-amd64/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-kfreebsd-amd64/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-kfreebsd-amd64/Packages.xz 589a0d6328a246508c14362fffa65259 117 non-free/debian-installer/binary-kfreebsd-amd64/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-kfreebsd-i386/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-kfreebsd-i386/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-kfreebsd-i386/Packages.xz 0b463c3a00fe3ebd875dd7795faabe17 116 non-free/debian-installer/binary-kfreebsd-i386/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-mips/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-mips/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-mips/Packages.xz a5146fc4bacdd167cc7be86231e52b89 107 non-free/debian-installer/binary-mips/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-mips64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-mips64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-mips64el/Packages.xz 21b7cbdd20ea26dd83b31d8c3842f895 111 non-free/debian-installer/binary-mips64el/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-mipsel/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-mipsel/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-mipsel/Packages.xz 0f7da028e5005e5d19386284091a326e 109 non-free/debian-installer/binary-mipsel/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-powerpc/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-powerpc/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-powerpc/Packages.xz 3c481bd491603b28ccef0dc33accdeac 110 non-free/debian-installer/binary-powerpc/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-ppc64el/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-ppc64el/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-ppc64el/Packages.xz d4aed8973b2fdb4ebe2539a352911330 110 non-free/debian-installer/binary-ppc64el/Release d41d8cd98f00b204e9800998ecf8427e 0 non-free/debian-installer/binary-s390x/Packages 4a4dd3598707603b3f76a2378a4504aa 20 non-free/debian-installer/binary-s390x/Packages.gz 8dc5aea5b03dff8595f096f9e368e888 32 non-free/debian-installer/binary-s390x/Packages.xz e7ceeb59c6faba0761d4bec329d3d26d 108 non-free/debian-installer/binary-s390x/Release 0d8c70d4810fc47c5574ea213a9c640d 47445 non-free/dep11/Components-amd64.yml 61137cbe5792a2e5ba604e230e6b3000 7189 non-free/dep11/Components-amd64.yml.gz ff2ef29352315f747293e44ddaf8d8ff 6624 non-free/dep11/Components-amd64.yml.xz 4c111a07a096bb22ae344787a2a0b5da 45122 non-free/dep11/Components-arm64.yml 0a2b11b7f8c0ace3bda202507458239b 6383 non-free/dep11/Components-arm64.yml.gz b857ec04a99d2bd5d2fd7918d5336378 5860 non-free/dep11/Components-arm64.yml.xz 846fd7550c016f1f937f5c169ee2ef73 45122 non-free/dep11/Components-armel.yml 2b41081c0d486828af96cc9ea91df4a7 6421 non-free/dep11/Components-armel.yml.gz 771901c6f9faf59ed153e341ecc5313b 5868 non-free/dep11/Components-armel.yml.xz 1d9f53e51cd5bea731edb5b2ac54899f 45122 non-free/dep11/Components-armhf.yml f0a9a5d74b7c9b32df0bd72af83edb50 6463 non-free/dep11/Components-armhf.yml.gz 2d076be34424c23c50d059632ec94fd2 5884 non-free/dep11/Components-armhf.yml.xz f1514d4dfd5377908c95ef1b5be233d4 47903 non-free/dep11/Components-i386.yml 9889d80e20699cbb3a7e4b8b63ee34ab 7512 non-free/dep11/Components-i386.yml.gz 63ca74d5181dd5e45f1ede237192437c 6904 non-free/dep11/Components-i386.yml.xz cf0a3a824d5b36b88fa02b39e232594c 46201 non-free/dep11/Components-kfreebsd-amd64.yml 66bc6b47f324b213c3b0bc3001adc1d1 6927 non-free/dep11/Components-kfreebsd-amd64.yml.gz 8b9fd3566dfb573bdfcb33adb28a51a3 6344 non-free/dep11/Components-kfreebsd-amd64.yml.xz 04004d656d3eae5941928412bad31c9b 45122 non-free/dep11/Components-powerpc.yml 3a8feb831b6dcacb673e0ab3ccf66580 6441 non-free/dep11/Components-powerpc.yml.gz 3c5bc01d9c759c40e202dd953dbe3979 5896 non-free/dep11/Components-powerpc.yml.xz 9999642388b37c5410858bbfc5ded8cb 30720 non-free/dep11/icons-128x128.tar 9d4f8d008f7bfb01e7a0cb59c2e284f9 20291 non-free/dep11/icons-128x128.tar.gz 5591cd3a317cc78d9c2e3e9097b6c167 17920 non-free/dep11/icons-64x64.tar 3b9db0b0b6fc27c1fdfda57f249bc87c 10022 non-free/dep11/icons-64x64.tar.gz a1bf9aa6de9a10af1f4128004b077cf0 374836 non-free/i18n/Translation-en 4457f974180756e905bcb6adbc8dafc0 79968 non-free/i18n/Translation-en.bz2 207d7da0217dfe95433d5441e3e0403f 25336 non-free/i18n/Translation-en.diff/Index d90d6c59bcfbf244d26d38dca492e911 109 non-free/source/Release d4192792d76738466a698895212e1126 344837 non-free/source/Sources 109518eaae9db1e0ca222a21cf2d0e48 27796 non-free/source/Sources.diff/Index a6025e53a124caa1909653747769499b 98981 non-free/source/Sources.gz db30aa8f2a582e5a7bc17ce090390460 82868 non-free/source/Sources.xz SHA256: bf829b9d7e546bbf1db28ddf3a73e77f7f93f67b91ae20d18ee1529302414f35 1318264 contrib/Contents-amd64 ab5bca923318b59d331499317b25c30f901f2e47d31dd5cdefe0eecf25477dea 23860 contrib/Contents-amd64.diff/Index d8556a0196c369faecf88c179a69cc40c47d415cbd88fe3ed38a998dd4e48fe5 101470 contrib/Contents-amd64.gz 9b36e83393744044bc4571bbeedcb0ecb498211a754414dd9f685caa0a5732e4 1175578 contrib/Contents-arm64 7fcfe688e3a1405f84ccc52fa1c37972df1050ff4c75614d14f67437d0404c23 18448 contrib/Contents-arm64.diff/Index e6a6f730b083d16d01ff2b373e2df4c88bd3b741d9f05f4541577d5d5040687a 87797 contrib/Contents-arm64.gz 1a6477d6fd5c244477f6e677bca783d66c0e121f845eabfd286030c51cfd460a 1177832 contrib/Contents-armel 7f9f1465482feff3671cba39d3498ecb64aac75d48d2011464f3cf33f05068e6 19432 contrib/Contents-armel.diff/Index 382df57a2efbd5baf8e4d53d200c3b1052a7bd56f044cb9f3a9a7c24687ad4af 88158 contrib/Contents-armel.gz 61c5a2da5a2fe2f7c55677e028f0a16c850a2494aa23c40ee1df0a678836386b 1164602 contrib/Contents-armhf d17a8ee62e75f8b9443ca6dda19fa60a585dbc94d5fcae9d7d64a733d413fe12 19432 contrib/Contents-armhf.diff/Index 5bb87109f97302af2c0ebf4265a847a40abe9ab07f1a363ed3f9ebbe32544cd1 87806 contrib/Contents-armhf.gz 76621d859ae45809fd32e16dafcdbd9d006e9ce3e3ece25b98a8e535a2326dba 1103107 contrib/Contents-hurd-i386 d7b5b0d20ae4ccaadbd1b9e22d485d8bb03c5d4e491303b7f91f792e2d66c982 18940 contrib/Contents-hurd-i386.diff/Index 4595035baf79710a4e815a97b8a5ce958eedec839acf0f9fd916d469d29557b4 80883 contrib/Contents-hurd-i386.gz 78cac2715a0248ec8cf654e5110f868ad8150b945bbf358bcf59f9c22708bf31 1290908 contrib/Contents-i386 51577f70807bc460f53804433cc04164a0a61ec8dc5b1885a9d28285b25eb883 23368 contrib/Contents-i386.diff/Index ec1cdfa5e88caa54d1c9bca8549cc2d3750b2ec6791de88793c89b434362bcac 99126 contrib/Contents-i386.gz 9037e8faf877ef7e6896dd775d15a8e19b6ff7495ce3882d83b0782536257632 1110069 contrib/Contents-kfreebsd-amd64 a5ec69d36e16d7ee56e6efb20f2245786a656f3dd2931656a350a2e2f0dc9f5c 17956 contrib/Contents-kfreebsd-amd64.diff/Index 7f42c4aedcf65663a9b836a87fd9e3008a53f7167e08ed56221a24f46d33b48e 81795 contrib/Contents-kfreebsd-amd64.gz f9cf27931323ef075571a3dffca5dcf83977970752c7d55fc39ca791183c2b6f 1109182 contrib/Contents-kfreebsd-i386 9fdac1b056fa31a758d23e24056cb55043261399f32275f8c53de297a8507009 17464 contrib/Contents-kfreebsd-i386.diff/Index 45429180529863f1a8cb7cc764aaaa97260bfa5033327f9f7d0fedb77a3242e1 81545 contrib/Contents-kfreebsd-i386.gz a794935674b9287803b6ed7c03bdb91a1fb03b3f23219980a2fa4f8c142222b8 1159398 contrib/Contents-mips 7e81b9f46f8c9290cd83a96154b65c372680af41bbe36c8f6b25141cfdc4808a 19924 contrib/Contents-mips.diff/Index 743114afe75f74144de2e1874c711cf32ff254e7528dde43b32caf9160ec69d0 86916 contrib/Contents-mips.gz 9375ad4cad79a2e584b5b56ffbc0d37b188036337d2b9978b9e9659e9d38dd7c 1151939 contrib/Contents-mips64el 97281609deaa3ca2adb23d5e6dd31c2481ae7468b0d1818da349bac1e9f6a5d2 18940 contrib/Contents-mips64el.diff/Index 8808223dee98ff200d94afba90b7e17d5382205b63489897f5b266bd839be261 86243 contrib/Contents-mips64el.gz a7248cf41cf4f7582308b0a19faf1e140e8e0bd6d8027a9e3f609afead138532 1159421 contrib/Contents-mipsel b687657154fd666d6845dc685622831a80c9815c5740d2af7bca08633c719d0f 19924 contrib/Contents-mipsel.diff/Index fd3fea533b1368c2ad5b2f74105959b351240566ae6e739f0b183a6c268c8545 86916 contrib/Contents-mipsel.gz bb6c8927ba12948726e4b4c0f70ab8c7b8c1be973dc2f4e6b044d1ff1936967c 1180561 contrib/Contents-powerpc a99de55e3fdb31a71a6dda91e1f03a104d3e2bb0ec61cb1a6a189d2703fd8e31 18940 contrib/Contents-powerpc.diff/Index 0fabc143d764e168c95874d711c97358a224a74988760551f93d4f50733e67bc 88488 contrib/Contents-powerpc.gz 20ac4bc872eca554d3068e9a643bd0ed16fe678bbaa694e58286673f12beb71f 1142562 contrib/Contents-ppc64el 24d692bce4db68b1baf0bbeed30a8a87ef33efca469336c0c2a73c0df9f12e7c 18940 contrib/Contents-ppc64el.diff/Index f81f1599796af960f64a1ab726b01aff8023e5e6ec8f058ba9fb05906e1441d9 85835 contrib/Contents-ppc64el.gz c0807bca647b9e0f4089125fad517bcbf1d5bd28afedddc9df7492fb6428fbe0 1155432 contrib/Contents-s390x fe9b1970c85a4b42f2b3209fec732f746492ed5e2ae1ac2a36e956452a373a8a 19432 contrib/Contents-s390x.diff/Index 185ea7e3893ce2f835835d45d79984aa574f728a708ee417859932aa5f901794 86413 contrib/Contents-s390x.gz f260d59581ec8a6186a656334880144cdfbc3c6bd930191dcc9c815890259d76 3519818 contrib/Contents-source a6e0b88b478d587aba4387c9c69460bf86521ed9903a9c02c98e40c423b138ab 24352 contrib/Contents-source.diff/Index 9526c7c619de2b5ff3dd4b7f83a71bd2fc60c46c67bd687b754ace8de084a9e1 389700 contrib/Contents-source.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-amd64 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-amd64.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-arm64 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-arm64.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-armel 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-armel.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-armhf 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-armhf.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-hurd-i386 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-hurd-i386.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-i386 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-i386.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-kfreebsd-amd64 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-kfreebsd-amd64.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-kfreebsd-i386 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-kfreebsd-i386.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-mips 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-mips.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-mips64el 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-mips64el.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-mipsel 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-mipsel.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-powerpc 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-powerpc.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-ppc64el 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-ppc64el.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 contrib/Contents-udeb-s390x 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 contrib/Contents-udeb-s390x.gz 1ea1989e37e40dda9c215e652ac3c935d6649f0a0914419e35177ccf68e3ab25 90903 contrib/binary-all/Packages 463e11941e379695305bc633fd891c832180e2a71d821eea09cb514d503021d5 26745 contrib/binary-all/Packages.gz 39c2cbecebdf636b1358becfa8b06f21087572a4e3c84124df9f72efab09a926 23788 contrib/binary-all/Packages.xz ee0fc1c54e8d7dd16c06529baa5cb605ae70f9b9e2e46737973b80a2d91e6f31 105 contrib/binary-all/Release 12c0df77c229d0e18c4919b695dd9117fb1689f31530ce2e05c4bc6290777ee2 224553 contrib/binary-amd64/Packages e56d7d0cdfce75a723483600892226977743d907c377bc26104253bf62d67c18 27796 contrib/binary-amd64/Packages.diff/Index f07a086987b992444c215a60862bccbc185c60bf1316e8755abedfcedd158ccb 62636 contrib/binary-amd64/Packages.gz 0f786f1852935e2adaaf5c0e788fc5ca9f70e7727afc3305a3a0ce9a76f5a721 52468 contrib/binary-amd64/Packages.xz 71490e3ed4b8693dbff8fabba92c4269580e5c8ca917687a1179723c60e92dd3 107 contrib/binary-amd64/Release 00b5edada3ad1f90dc26a03a06abec4f1a0ee9d398b62fd9c71a05a780846710 173735 contrib/binary-arm64/Packages 5497271dccea31838151b903f242b47731dfb6c897b370604a1f614fbebf7d71 27796 contrib/binary-arm64/Packages.diff/Index f2c1ee4ef17b110475ea8bcd0efbb26ff0c60e0fc9c33e856804bd8e098ca93a 48846 contrib/binary-arm64/Packages.gz 06c36e7e8bab6ad2f3de2d659d4f4a59676e2e7a1c876c50bb0219d48b54673b 41604 contrib/binary-arm64/Packages.xz 5a270e8dea0fdec6a7ed08da01d439832f5c344909df7bc9ccb9e8ca4c81b53d 107 contrib/binary-arm64/Release b054d3a8fdf7e08073dc39f89f93b181960aace7cbca39c6ff1f8fcabcd4bdd3 175162 contrib/binary-armel/Packages ffd6f56218f57ce7f871af0265d480b013c207e6776dc79668e9da682a9a120d 27796 contrib/binary-armel/Packages.diff/Index a06d6f53c62c8b0600939389b62ba31683551e0855f6db530e5d262af1e6d045 49399 contrib/binary-armel/Packages.gz b1f0dae364c8219ba8047a15218eb03b4670892a5458673bb4b2292061338f44 42060 contrib/binary-armel/Packages.xz 6263dd4ca1f185b99ab37a1469467f45a945e04f36b448e4357643ab3d52ea75 107 contrib/binary-armel/Release def29e3d5b1a0df2266caebbebb94a6891f3565085881fd7276a8741956ed81b 181954 contrib/binary-armhf/Packages 4a0f54805991a15330df30a3ffc40e15f07d50792eceac5e9c29f2a27eb4fd5e 27796 contrib/binary-armhf/Packages.diff/Index 6d1562abdc002652a901a24e5c0da959592d856e58b4a1e1d02b1ed54110c83d 51101 contrib/binary-armhf/Packages.gz 993d0bd9f4390f9813c102dded8b535379d73132bfee180e7b85906f5d441be2 43400 contrib/binary-armhf/Packages.xz 1768bea4edde872aab0d5f086bc86bc256db503127ec434fe8d358617be1b76a 107 contrib/binary-armhf/Release d7c74c7e9a0430fa5b9eac7ba1ae935fae3687d92be253b4151c89953e634dbd 147251 contrib/binary-hurd-i386/Packages 410faf6bdd56fdbb6c86c66b710199d08eeac35309e606ff6c2070b6898c833d 27796 contrib/binary-hurd-i386/Packages.diff/Index fcf5759143512b23025e72283bb21f9ac5a534719a9b33ebcfa0be5db2b53e9b 42491 contrib/binary-hurd-i386/Packages.gz a2c012ec62047685c6c88074a28e34ff3b538936037ca0b527c26e816de75646 36440 contrib/binary-hurd-i386/Packages.xz e68963de7ec8a12061249ab755334be781d8a50ddc50748a317c73280336f569 111 contrib/binary-hurd-i386/Release 267e7aea22b22e99de2c7ba5630841c35ef141c707b08d28105613442905f91b 214181 contrib/binary-i386/Packages 4c737caa1250f6ccfacf44364cdc36549dec65377e365b1363e761e758e863af 27796 contrib/binary-i386/Packages.diff/Index a98040341e6a86f4c389dfa85c8a03dcb75c4177c46b6838c9049394f7ab809c 59731 contrib/binary-i386/Packages.gz eb80caa293ec826e4fbcd40668ee5158a467b15492b9ec9c3fb3d2818ae2cc2e 50404 contrib/binary-i386/Packages.xz 58f7a0b704e8d9ee2e832921e7c192be4787ee5f0c0d7156ff92b8d46aa452a4 106 contrib/binary-i386/Release c948929837d7911de9132656a8e52b3f7987b6e91c6c40926af92654240ade13 156547 contrib/binary-kfreebsd-amd64/Packages e66f6e99a8f7dc319b9bda3403a244a0473912a811282b2c83ca2df327de62f6 27796 contrib/binary-kfreebsd-amd64/Packages.diff/Index 7a6b4a359c792325526b74e3359c654d556d60838e7cb95bdcc3867625c5a5bb 44496 contrib/binary-kfreebsd-amd64/Packages.gz c619628473073f0dad2dea7ba6597fb75808201bca49518348b309a6482cbeb0 38132 contrib/binary-kfreebsd-amd64/Packages.xz cb57e35c4b6f12a1f7748f5a2cc4ff1716bc6b6c41e61a22b8784703716f6c1a 116 contrib/binary-kfreebsd-amd64/Release 47ce85d78a9b1e71faff4f1d824e6b00523167dd3bf0c1654984c8c9a57d06b9 156427 contrib/binary-kfreebsd-i386/Packages d503ee74a30afdc2655f6337c66e84dd4200c2f70548e4df7f61b6a74064c1ae 27796 contrib/binary-kfreebsd-i386/Packages.diff/Index 3dcaf601aee0f58d869f17485195cbde4575df497b70222b3aa5fb7d225bf139 44488 contrib/binary-kfreebsd-i386/Packages.gz 9b78795b34651bd2c1a7e70970bea1553afd625731fff10911d7324f7c87807a 38184 contrib/binary-kfreebsd-i386/Packages.xz 996020567cd141c5c6f913f468bc135dd64be57451ced8d4a05b7c392f7a455a 115 contrib/binary-kfreebsd-i386/Release de9956e00c161bbcb834192e56ccde18d71cb8a6b4118078d25f93b87cd09cb5 173496 contrib/binary-mips/Packages 5c754744e81b140f7e690c701b182e9af00a734458d370e71d54807ebdb0a2b9 27796 contrib/binary-mips/Packages.diff/Index a265202b13f18a6806b3df639675c629e27f6ddc3a05e8b9445079fd478fe4df 48888 contrib/binary-mips/Packages.gz ceb47b947b3aa7e6f487a61f6828be1ca7f3dedaa7247000bb9ca9af5e7919e5 41788 contrib/binary-mips/Packages.xz e49289714a6854e16ead5461848a9957f79ce2f0307542601af39c4c8459ce4c 106 contrib/binary-mips/Release 950648b6bedafaa9022e7e527eb1ce76fd4f60ca92e2bd7f2ae2c313bec2bf99 167584 contrib/binary-mips64el/Packages 4c598a298d38c762d63b94d40564f6a6d2f58cd30ed76603b416a456f22c8b1f 27796 contrib/binary-mips64el/Packages.diff/Index d2edf9f61acf1c2bbbb700b682279411ff18229069e2f31804e08e7941230454 47081 contrib/binary-mips64el/Packages.gz 93035259c23aca915d5870864b552f3fe76839710cdb99cd54948fc4813d9001 40424 contrib/binary-mips64el/Packages.xz 00181dfaa08ecd4abab02a610866aa334fd1a2dad4314e8faa5adcc4427ac80d 110 contrib/binary-mips64el/Release 4ac2a145c535a3943bfbdcea4be99a5a63de1642bb42811a30cb34a921851938 173896 contrib/binary-mipsel/Packages 2ea3f7225ce31cdfb039b587051ad60984f2b2c3a6bcf93377d733874ee077e1 27796 contrib/binary-mipsel/Packages.diff/Index 642ec0434e7d533a201b520346bbac9967949d5286315a4212fada7f6ecadd2d 49030 contrib/binary-mipsel/Packages.gz 274b6236427cd7d94da2d2da55d1251832a6c552a719b53cbeb8e17636d43378 41792 contrib/binary-mipsel/Packages.xz a1bd09097f80e277ad3a05af1f8428ffce1bb52e64bbe6ae3e56f8b2ac22740c 108 contrib/binary-mipsel/Release 3977d5f4dada6ee41dd0b4d4b0468014188952229eb8442d6b6752c9fb064ad0 177845 contrib/binary-powerpc/Packages cb499b93a201f701abcb3228e75941a7b0f4aa2c1cc12b9060400b0c76a0c5cc 27796 contrib/binary-powerpc/Packages.diff/Index 45205d404b8239dae53596c6a1ccf2d5043bb0ec19e586d926c1896b879bfd07 50212 contrib/binary-powerpc/Packages.gz 52b942cae4ee8188c9599f3d8afd2cd3179d270000c57d67f1e013f713ebce27 42644 contrib/binary-powerpc/Packages.xz 181b6b8ee07f298141eb500b77df63ec8acd1bd4cdecb21fd7d14d67670ff19b 109 contrib/binary-powerpc/Release e7ca4866f44abeb26a55f0f07336bf65373af386c3dd9b09d42127c20b7d4958 172740 contrib/binary-ppc64el/Packages 3b2bb1d0adbe3f2639835f5a90f9b38279134c36a2c930ddff65abba9089fc14 27796 contrib/binary-ppc64el/Packages.diff/Index 82b29a770b41b119565f463d7f484a9e6c9444a633fc11df9c823dc61247e63f 48549 contrib/binary-ppc64el/Packages.gz d1523d88aaa31a4d82199d57d318c8fe0be1cbcd3f3fc14ee823384ab072378d 41448 contrib/binary-ppc64el/Packages.xz c6338b206c1fbe67f93d3d0e27d2930c6eca65a5beff7da3424264ba555b9605 109 contrib/binary-ppc64el/Release b9a0264481d72145a597ec381b331c0bb53f7a97cca5727ee41a78558cfd8a51 170484 contrib/binary-s390x/Packages 1238a854a54996aea3fb6a5b1641c31c5aa5145abfdd8a65db061dbd6b94946f 27796 contrib/binary-s390x/Packages.diff/Index 5782269ecdcf30e029cb1dd8b2b91c50f0686d3feaac385f506a7d092c62f544 48250 contrib/binary-s390x/Packages.gz 771f6cb295fd5076a880d48131d137ebe0ff485b567baf66425766d11a98e8c9 41044 contrib/binary-s390x/Packages.xz 0aefde72db93681168f317101bc2f41a38f560db2b2589c4dbc317c5362967ce 107 contrib/binary-s390x/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-all/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-all/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-all/Packages.xz ee0fc1c54e8d7dd16c06529baa5cb605ae70f9b9e2e46737973b80a2d91e6f31 105 contrib/debian-installer/binary-all/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-amd64/Packages.xz 71490e3ed4b8693dbff8fabba92c4269580e5c8ca917687a1179723c60e92dd3 107 contrib/debian-installer/binary-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-arm64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-arm64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-arm64/Packages.xz 5a270e8dea0fdec6a7ed08da01d439832f5c344909df7bc9ccb9e8ca4c81b53d 107 contrib/debian-installer/binary-arm64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-armel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-armel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-armel/Packages.xz 6263dd4ca1f185b99ab37a1469467f45a945e04f36b448e4357643ab3d52ea75 107 contrib/debian-installer/binary-armel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-armhf/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-armhf/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-armhf/Packages.xz 1768bea4edde872aab0d5f086bc86bc256db503127ec434fe8d358617be1b76a 107 contrib/debian-installer/binary-armhf/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-hurd-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-hurd-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-hurd-i386/Packages.xz e68963de7ec8a12061249ab755334be781d8a50ddc50748a317c73280336f569 111 contrib/debian-installer/binary-hurd-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-i386/Packages.xz 58f7a0b704e8d9ee2e832921e7c192be4787ee5f0c0d7156ff92b8d46aa452a4 106 contrib/debian-installer/binary-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-kfreebsd-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-kfreebsd-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-kfreebsd-amd64/Packages.xz cb57e35c4b6f12a1f7748f5a2cc4ff1716bc6b6c41e61a22b8784703716f6c1a 116 contrib/debian-installer/binary-kfreebsd-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-kfreebsd-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-kfreebsd-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-kfreebsd-i386/Packages.xz 996020567cd141c5c6f913f468bc135dd64be57451ced8d4a05b7c392f7a455a 115 contrib/debian-installer/binary-kfreebsd-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-mips/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-mips/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-mips/Packages.xz e49289714a6854e16ead5461848a9957f79ce2f0307542601af39c4c8459ce4c 106 contrib/debian-installer/binary-mips/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-mips64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-mips64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-mips64el/Packages.xz 00181dfaa08ecd4abab02a610866aa334fd1a2dad4314e8faa5adcc4427ac80d 110 contrib/debian-installer/binary-mips64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-mipsel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-mipsel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-mipsel/Packages.xz a1bd09097f80e277ad3a05af1f8428ffce1bb52e64bbe6ae3e56f8b2ac22740c 108 contrib/debian-installer/binary-mipsel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-powerpc/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-powerpc/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-powerpc/Packages.xz 181b6b8ee07f298141eb500b77df63ec8acd1bd4cdecb21fd7d14d67670ff19b 109 contrib/debian-installer/binary-powerpc/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-ppc64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-ppc64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-ppc64el/Packages.xz c6338b206c1fbe67f93d3d0e27d2930c6eca65a5beff7da3424264ba555b9605 109 contrib/debian-installer/binary-ppc64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-s390x/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 contrib/debian-installer/binary-s390x/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 contrib/debian-installer/binary-s390x/Packages.xz 0aefde72db93681168f317101bc2f41a38f560db2b2589c4dbc317c5362967ce 107 contrib/debian-installer/binary-s390x/Release 78803324d080a7b582ee0019e2e1e2ad88b81c6deec0fa74640b3ad9c6fa239a 37465 contrib/dep11/Components-amd64.yml 4e7d5b7881a856935b6b24fa3ca0406d8481c864034b5a4a57fef15308e43d53 9645 contrib/dep11/Components-amd64.yml.gz 2061e19433c9f9636aaef0ea231dd5b3652cb599ecb293bf809bb6799d1a8034 9052 contrib/dep11/Components-amd64.yml.xz 8d42504a336fb39b0822c62ea4ad541d101396e54ba445b1e2fb08fc52bdfa7b 33085 contrib/dep11/Components-arm64.yml ddcd1c524806b5566b61b5f40c1ae4f7174c9232d417c5f60147414f18013759 8364 contrib/dep11/Components-arm64.yml.gz 44e353dfad2a5be0a64707c25a19ca07bf43f4e532ac026d348da31004906eaa 7872 contrib/dep11/Components-arm64.yml.xz 040a21a982ea92421bf97e5e09448f2f1b0aa808d9ca40acaa0d86e336627983 33085 contrib/dep11/Components-armel.yml 332ffa4734e92ad7c8feaf398473517b5058b86e99736b5e42692ddbd7771303 8255 contrib/dep11/Components-armel.yml.gz e5c0382a448aec0f5118c3d8d82eb408196ca394959689bac38a44b6b4f2b5ed 7832 contrib/dep11/Components-armel.yml.xz 79e3101f5d6491a7a49ff98323498aaa470d260a0edd04021c8f8cdd6d145b0b 33085 contrib/dep11/Components-armhf.yml c7e6ce867f6b68ccabfdb28be189401578aa5f0c2670c8164cfcf0afd050d724 8344 contrib/dep11/Components-armhf.yml.gz d03bb387c09e6ba87b3081ec501be351345e9232f7f8fe0025fef8beeaf52d36 7860 contrib/dep11/Components-armhf.yml.xz 437e11772ff3b605e6fb72637964ab1f87890dbcb09a24eda6604d538e7cfad8 37465 contrib/dep11/Components-i386.yml a191ae6e249fc6cc2a36b9a8d099c00f896e5b199ea9db9e42a587d63aa130da 9620 contrib/dep11/Components-i386.yml.gz 65823984f864de6cbb01eca72114d9aa5452f94489bb2d44fb14fc4a15ae344c 9052 contrib/dep11/Components-i386.yml.xz 1350606ca684e6b33c10baba53b221417658e6e874dc7dd0c8ba23bf3d0e2cb7 31558 contrib/dep11/Components-kfreebsd-amd64.yml 5aa324f0a3d86754f615547f81a3098946dad126898a114bf3384b1aa25ae2b2 7777 contrib/dep11/Components-kfreebsd-amd64.yml.gz 8ba91b03d935a3c1b27b2502d4b84fd8f4802798a1306ecf9e5f7d31681a8b89 7328 contrib/dep11/Components-kfreebsd-amd64.yml.xz b6f4ec3d75799ba55e273013e16c565435d22cec1f953850ab25b255c894c1e6 33085 contrib/dep11/Components-powerpc.yml 70738901d0e9380795c42f8912a75255875182e85e29f3f0653994a0d37620bf 8314 contrib/dep11/Components-powerpc.yml.gz b372cd613418c5aa2c007c769681d371bcf9d1b9d64f9589f5ee8c08ad1bbb50 7864 contrib/dep11/Components-powerpc.yml.xz 7212d818f92be37551ab43b69c5e8407dbb1fc6d284b87a499f9f2ba2ebe6c46 372224 contrib/dep11/icons-128x128.tar ae92d6c1fad90050aacc63f8ec533470b997b7a3ae1ec2a52eba6dda005218ef 304821 contrib/dep11/icons-128x128.tar.gz c7ad3e1be349e072e5573ca6af62e2ac39d37736a055fc95f3f16b1798690ce5 160768 contrib/dep11/icons-64x64.tar b9c9334927887f5fd32145190e9bd95a36591f93da1ac193a8128c4a20943c0e 120717 contrib/dep11/icons-64x64.tar.gz da44e12b5a6d7558895de021e780837656f411fea9c88b4255701916b947a936 180882 contrib/i18n/Translation-en 6d16a7bc3696e35f6479ed18ba8e90c3b9dffe2147f81d02707f3427b80f84a2 47717 contrib/i18n/Translation-en.bz2 69dec5274c95b0631e486fd3d648df374c1dccce066188db40ba97e0a822c645 12544 contrib/i18n/Translation-en.diff/Index e403c8d0095bcf93eef7d4360dbdb20089048b68afab3d91426ff1e2c8f48d76 108 contrib/source/Release dc48b06a2e96795f1a6f4c45f56c240b67e565f66ce61582bdfd82cf7e17ae5f 189731 contrib/source/Sources ff30ad72c4c4b7570435ae32862f412eaa3c90d3c6985205287ce5c1e38a8eb1 27796 contrib/source/Sources.diff/Index 2a18ad43b0b5c24a64131651e4e7c18dc7b24bdbd9172b05071e6681cf0e21b2 56034 contrib/source/Sources.gz a1548fce14a6d0ac8b2e8aa86ac38a5d90f1b5cb9bacc0ea8592bb321ff57573 47676 contrib/source/Sources.xz 6225e8292f73d39299cfbd47f3b4254ec305a88b2370deafaf1f8592eb52d124 486486404 main/Contents-amd64 b2775e7db3cc971e7df8b51fc12c0dec3ac241cb1f8664d11c04b6d0f546dba2 28024 main/Contents-amd64.diff/Index 098b4d2ddc6c0f72a0e0a326e1f3773df7f836a6aab1022631c2c69c3c4669d0 33741709 main/Contents-amd64.gz 4f2d4cba3efb61f71756101e3c70a74a0d77caf3c2b394dede1eafef6405c325 464406406 main/Contents-arm64 9b8ddf71ca6d99bb0704d498913c899a4e2c1806d08c5ffdecf74c87138fb057 28024 main/Contents-arm64.diff/Index 7e9e7275a41953053551debbf21da8c65679e314b4932f12057f81345872f8c0 32427484 main/Contents-arm64.gz 8230fa913e1e95058d2916706f7112a5847c93f881a217f5feb878360fadb74e 462714353 main/Contents-armel 6fa0fda7a0e268394e70af0b5cbf80402b68cc0782caabef8952cdc6175a061a 28024 main/Contents-armel.diff/Index c1f16fbf62d2e33ffaf7494e23dc48d39717d0c5d0eb90a41a0de45eff8599c5 32372160 main/Contents-armel.gz a1737895549660f27229c2e0d519ebb3e73409f0000a3524952793bcdb7a49cc 465331124 main/Contents-armhf d4ca75f069bd2a71ea4e9466bf9303504b5b97c0308e6f34c2324d325d5c9f68 28024 main/Contents-armhf.diff/Index 338ba9c6ba391348a0f27ab8221b79d80124fd45177a4778d98b4cd034e5b6a0 32551542 main/Contents-armhf.gz 12164d6ca2768ee4eada8214439ae38099507007ca58594fe3f26d5a8c7d17fb 437011535 main/Contents-hurd-i386 d7350f21962e0039b025a8617603732410c75833e3f3237d58816b0d02bdf1ca 28024 main/Contents-hurd-i386.diff/Index 42d44861b008f6db216c3a3ba6567998fceaadad5942242c731549a8da7df6f0 30282285 main/Contents-hurd-i386.gz 7539740c4b23e36bd0eaa28932fe789ee0b3da2655b2d70a92f564e5b17dd703 484515088 main/Contents-i386 b45ff8daf9be2d182cdba5f19a61e9e0f33a51fef65d38c73cd423892ec1e0aa 28024 main/Contents-i386.diff/Index 90263a4a8f933e0ac015a657c2f02398d003380248f2289e5c4ce5753e206a61 33649417 main/Contents-i386.gz bdcba9995f0782c9243f7f735172485c09719357cce8a15a243827ac3d3ae750 449136892 main/Contents-kfreebsd-amd64 49a32acaf40b0e20393786fda93abdce653df535f8b5cb76eed693912d4bde40 28024 main/Contents-kfreebsd-amd64.diff/Index de09420766148813556cbbad3871290a355a67a28b1ab63948ebbddaea6192b5 31341686 main/Contents-kfreebsd-amd64.gz 75ddb564e556de94bbea1bdfc368ff38011e49eec4f4d8834c6b99a722549e76 448627460 main/Contents-kfreebsd-i386 3976553adcaf1deeb11acd7007769542a27c88b557867eeaf7abf0714f22a80e 28024 main/Contents-kfreebsd-i386.diff/Index e932f6b3a78ce076c567e402ff94a6f9d760015ea3ded01c8ca191d94c745e0f 31305004 main/Contents-kfreebsd-i386.gz a15462d0ceb1767fa8ec6e417892435ac9aff42270aed4f368eeeb7a80f9159b 460036580 main/Contents-mips 321f2afa5a49320dd1eaecf1faeec7686d7a1770272be2ef5a8ce6265791812f 28024 main/Contents-mips.diff/Index f894fbe0c5b6a5b9b166faa760402debab16abc724e2449dfd13fe5023e3ca19 32236221 main/Contents-mips.gz 5198504cf1241a5f6ca4ae597b9a8b1c2cf8fa59385f50cd8afcb21034c66971 459438445 main/Contents-mips64el 47d5a126188417ed83fb74c096e3e503a9d0bc3756bc1f92144f7eaa5a515791 28024 main/Contents-mips64el.diff/Index 8ee370da3a1e6b9a3f7632a41e5d8c54a605268baf5431906e62edd4359e048d 32030589 main/Contents-mips64el.gz ca351edb83bbc6173e4f54329ea358d52fc7a8a5da14a29ececc87d58f960e19 465041084 main/Contents-mipsel 603df43e401e4a0eb1f4a2c71b111925d37604eabedb33742b756eb928a8414d 28024 main/Contents-mipsel.diff/Index 8bf4724562bb6da2a84c536a1c81215f60c2f3c824d44e23abe34b35b5f7c96d 32541643 main/Contents-mipsel.gz 9ace3630938979046fdd74a844369edcb1f3ef2189cba2b31802cb20a3f51ac6 465654055 main/Contents-powerpc 0715a66ffe4877045aea9fa219b383ae9f4885d8240f0c09eca075aa52c7facc 28024 main/Contents-powerpc.diff/Index d407db7ddf9defebff35daf0d7cdb8af7b3a09bf5ba250b00133dd9f1adcf38b 32538984 main/Contents-powerpc.gz 71f19e382c618b8718ec6e7b2ef852d9b9410879010d15f4e2dcc29e74ce5291 462882892 main/Contents-ppc64el a117a8b76916ae3f5abb0fbe4d782892ece677b9880e81c54f24b1231d89e26c 28024 main/Contents-ppc64el.diff/Index 6299082dabeeff4059fc802447ec43ef7cdae2f9072b7e83d9b503092aff8873 32352649 main/Contents-ppc64el.gz c96502c6d78173e932c1998414d753ecf19e4e903f273360834e4b981857722f 459302164 main/Contents-s390x ef600d65d3c84bbf294819c62d7e586b62ee84b3c65a3b3fdc1a9062e69abd28 28024 main/Contents-s390x.diff/Index bd69285fb34ace9eff6e059d94b4f5db47d2ff2c4c4b68deeb352797f476618a 32174741 main/Contents-s390x.gz 151abe91c34c7ba0f9d7ea77bf3d447712dfa558c6d903427b0b56c498067049 482453699 main/Contents-source ec81b1518bda86285179b3a39914fd23946572031b687206d63106b97b92f8df 28024 main/Contents-source.diff/Index 2f38e5ed5a80d3ab28db61cd585b957bf4a53937682dccfbfe76c076dde0a311 53745770 main/Contents-source.gz 87b1f789988db6646307ce219b6913aef080672629c6c838d3e7023123e7937e 484751 main/Contents-udeb-amd64 af8ee15ec674e995fd85d9b5cfbc781b00af18c3267f19a8c43d00b1f5710741 38535 main/Contents-udeb-amd64.gz 119c16a23678425b7d07faa91740d81c3cf33a7112f3574b34597319b7773a61 419372 main/Contents-udeb-arm64 c964c023c67a2557ccf91b163b6662e199b35ab4c553b11e1169df31da5460df 34115 main/Contents-udeb-arm64.gz 630cb57f948c63dcd57b173b1e587c3daf3f072b625efda5bd6e47314ab6f5d9 414623 main/Contents-udeb-armel 3fb372ba3c72606f9ba433c20a0f3be6279d86135b174965335101cee6a2515a 32491 main/Contents-udeb-armel.gz 2948576d7aff0f15b6d3c2b274661cad417c1ca5e86618a646d22df9b48bb8ed 504043 main/Contents-udeb-armhf 1a4f163635930d02305aa4f52125da4b28a2de5728efb542d674810e5e75d521 39965 main/Contents-udeb-armhf.gz b292917984474cf3a7d58273af21949eed87a1c2e88a0346a9315046b375dbad 266208 main/Contents-udeb-hurd-i386 f935fd65dd1de5de4a8d3b2cdc55d47fa27e70aaa44efc66252adad89d2a8a4a 22517 main/Contents-udeb-hurd-i386.gz 998617b62e2cd1cfc818d0c4d07e07b2c5942c1cedefb699569d779c6f95000f 710802 main/Contents-udeb-i386 7cc1a2777814d21705cac5f5bc4229b7dba2aaa69b29d088bc73d2619ee67a80 54082 main/Contents-udeb-i386.gz a948334097278469ad5bf3dc366f8f525d7ebddb0ffae8faecf3827ef67ef24d 289951 main/Contents-udeb-kfreebsd-amd64 55c62e343faa3f8cb5f5ff4df5085fa05feafdcdbb0ccecde2a4fb89b980ed35 24182 main/Contents-udeb-kfreebsd-amd64.gz a9e7d3a6342280744a286310ee0b9ae048f56b329896f2909f376a97a39f30ab 289869 main/Contents-udeb-kfreebsd-i386 740e1b1712b39d3dbbc2889708b0f933b5d728a61d8a5866217075769d907f87 24244 main/Contents-udeb-kfreebsd-i386.gz 5a49f76c89934dccc1b80ba58aad231bacfd7263f4be50de1b74c9db725275ad 577017 main/Contents-udeb-mips 928fa491edc0df94fab8430f5b268542f057b312c28c9487507b2dda68b43d41 44213 main/Contents-udeb-mips.gz 047c1d01fdd2a46d26731c277ed0bc1c7d5bf17846b02ad394ff0b5e47202425 723583 main/Contents-udeb-mips64el 501ebe45aa5e0b6868bfc10702d14b40b5c0fc7ae77e2aeaa28b78ea7ed62204 53323 main/Contents-udeb-mips64el.gz d11db1a1372711ac5b0cd4f100176b9cd6ed9f61165b108a674f1d44d7dc4119 1008989 main/Contents-udeb-mipsel baec12d4d9cc94be881b304becda72a351b5945360631c9dc548cb8a59e02a67 71028 main/Contents-udeb-mipsel.gz 3c2c2365976c953d4d3197688f0f93a3e5801930f17c3069d67e4f4c6d845459 583828 main/Contents-udeb-powerpc 05a72e24f60d033fa4129501b838382a1ed6f10e49bedc813430a6484d4305bd 43594 main/Contents-udeb-powerpc.gz 645c1ffb53890a79a889ce0620a26497db79ea26258d739a2c0a116ba482ac53 396155 main/Contents-udeb-ppc64el b978f738e7d73e9368a69eb28d6b316a985e65bc5d2b6e8c470b002604b397d2 31809 main/Contents-udeb-ppc64el.gz 2f25f40a1fc13ccd5facc9a6af3821ba04dce9eb4dadab15ac4764437bf83bd8 307502 main/Contents-udeb-s390x 825cead37f987b4432724197cd8cc95cbd33e86c5da6b18b3ad94fa7bf11c353 26131 main/Contents-udeb-s390x.gz a852b64970a8ffe3b26ea70c9672af5b8ad2f135ba404b88606509568d8b527e 17781690 main/binary-all/Packages d8d49a3ea4ffed502df05687f1aadb88f59810c5365bb3c2634d32b793278126 4391664 main/binary-all/Packages.gz fc36847abbd1e503068c1fd933490d4d2d1088e4ddca65f771ff5daec226c121 3337812 main/binary-all/Packages.xz 426d4a8e95369e5d97171b4e8e5dd73a1039231d256e35cfd223bf572be116ed 102 main/binary-all/Release e7a8f1dd5b54a1600a4bd3505e9f4ded10cd3017f47dd79e3aa0e4eb102b788f 39256459 main/binary-amd64/Packages cc5ec05a29811cac40dc601b31c926063061d985ae83bda66b27b4109ecc0d8d 27910 main/binary-amd64/Packages.diff/Index fa0a858a78634103379a48636ad32983e253bf693488519f59bd82d231d89e64 9576288 main/binary-amd64/Packages.gz 24f6cf9b24e3d5f10b297dcc25c12e323258130625e3ec7de51419b66d2350b4 7147528 main/binary-amd64/Packages.xz 07cb692d133dce21dabb9e42201b8e632a7c6a069b53f9ae8173a4ea24606da9 104 main/binary-amd64/Release aea1f7ba403d6f839517644d48f224cbfcc2124f14825f25b93bb7116ca46e57 37571520 main/binary-arm64/Packages 5ac35ae5d5d97ccd2c662fe3a52f16cf59703f534fe254f8185582827aad1ab7 27910 main/binary-arm64/Packages.diff/Index a24fa93bdd882e9b860957b7411b8230ad59030cb3e8a7a2ffe40fe20ff40e13 9227318 main/binary-arm64/Packages.gz ee29d1cce5817c25376ba3319d359d370c8122ec842518d4a78f7195c0887068 6884520 main/binary-arm64/Packages.xz 16b43705f8420470a43f96954eb7d00a75c4408a36c1b86ccf2bd6cfa4ebfd98 104 main/binary-arm64/Release 5518a06473c0cd4edd4ccf12fc4d56397571887e3817b3c86186a1a833579e16 37699046 main/binary-armel/Packages 63c0ef80d23c66ddf5cc78d76a0662b40b72cd379f163817b9aaaad6ee3f989f 27910 main/binary-armel/Packages.diff/Index 1aac32bbb9e5bf5f4cf7b99034611cd8ec1134a75ec4897fac529f29b30d933d 9275300 main/binary-armel/Packages.gz 94e5a90f20410fb4d87451bb5ad5fe363e418664324ffedd809b00db2deb30f3 6921736 main/binary-armel/Packages.xz 82b62056193684651c2bf9ceb2af527cc75d034576d4cb3bc9b2f95fabf93e8b 104 main/binary-armel/Release 5764f36e2223186bff0fc3306900ccad92e8e8b8b705b3d289f5d1c5898f2e37 37788052 main/binary-armhf/Packages fc39c2a13723ce15ed7bd1323c625eefe63708106d313d0c26bfe303c99bf4b4 27910 main/binary-armhf/Packages.diff/Index 73614cd887087b115a5d51f5d4d69a8f56f56b8a51d8e2231f8b03c8b7010a3c 9300334 main/binary-armhf/Packages.gz c11f25f4cf6b37b33ba284ee31a960c230a3213e557277e3cd2382a722791e02 6934520 main/binary-armhf/Packages.xz bde8b39b284457d38e4af1f04f9de8e73a8705795de39525a6def7d42e523396 104 main/binary-armhf/Release a4aabc159ce2439c60a0f595e8bb474303966d85bd37a880e4c93c86a47c07d1 33806130 main/binary-hurd-i386/Packages de4dc855e795cf6e73d8d9dc1bc6f9d6cf523bb9b653f6bbcdbea1fea25cadc0 27910 main/binary-hurd-i386/Packages.diff/Index a1812e288764d013f66c5b9baf3d9a895cfe1f6152c806ceb72d8394ae1d1ed0 8234995 main/binary-hurd-i386/Packages.gz 0ab729453f01a564261190614151fa3391261815ef771cc1c1278b9ea4986548 6163664 main/binary-hurd-i386/Packages.xz 141c84b75fc4356d505e86c6603dfe15875c7be89f23b4e99570b97822110b67 108 main/binary-hurd-i386/Release 96fdb290724544ab3ed6f34563d96b13054b3ec219ed84588ec32e233bb1b172 39044462 main/binary-i386/Packages d1a7007422124bf288ac478adfc7e32c6db4f4cf7e84cfb9e07aa035fe302c1a 27910 main/binary-i386/Packages.diff/Index 0424e96da42d89dc31b7a2e88ad7b34fb0d48c1943b109dcca3abeb148794d0f 9548697 main/binary-i386/Packages.gz f121096021939484b9f54001067af8a686291e31ad98968978ef7b54036762d6 7122292 main/binary-i386/Packages.xz fd5827463ef11fa7a4c0777a83766441d7a730109e012830e7ded5aa051042f6 103 main/binary-i386/Release f8ee3c831a70de7db68cb615ac5c886398a5025604ad4f58afd1f806e7c1eed9 35913320 main/binary-kfreebsd-amd64/Packages 5ea30ce949672beacb096f8dc16c99052448254c10dd459b7579dec03bf543a1 27910 main/binary-kfreebsd-amd64/Packages.diff/Index 2b9827f5561975831e609fd73aa6f305fe46848a6f8989fe951aa4cde84ec60f 8718641 main/binary-kfreebsd-amd64/Packages.gz 93a4d574ad7d1c7d430698b2fcbe7a390b663d9855339075d8b39f3fd03858a5 6512728 main/binary-kfreebsd-amd64/Packages.xz e9cb26effa2842679d46dea78abf7662b5a75320e0dcf15054164abee90df89e 113 main/binary-kfreebsd-amd64/Release f61f0a57cd6e3b90f29df78ba6fc5936fa930f58df4c44eecca39b5ee77fe844 35809649 main/binary-kfreebsd-i386/Packages 4c076575c95105c382338d83dbd5021c17b10123f2c25fd957a83109a1cf0c55 27910 main/binary-kfreebsd-i386/Packages.diff/Index 62ffaa506a24593028cfc049178c129316eec91611dec632e8dda7c6fbe00e38 8704036 main/binary-kfreebsd-i386/Packages.gz f5a48fe4984d5db55e638cd42474d5eaa1067b8bb124fd6e2564209258033c77 6502680 main/binary-kfreebsd-i386/Packages.xz 0f5494dc8749cf8141c7f288273c275f7ee50c1b37231418f1db376bb7478b83 112 main/binary-kfreebsd-i386/Release 410e9b3fa8a7b06d40de71111c99aba20c0aae3df9c4fc26adbfb9092ade2c87 37366754 main/binary-mips/Packages b1b87da67376841c606df73e2db8b4be71cd3b9b2ba7a84bf281e92ad7445604 27910 main/binary-mips/Packages.diff/Index d070dfa70e6aa55836fd4855d25999dd1056c3f59cd227fed0b11f2e8cf293b8 9210212 main/binary-mips/Packages.gz 7624f9dc42e9f09da0b34e7b41812f0f38ab8425c7ea746d08a3731dff3d8a4e 6873512 main/binary-mips/Packages.xz cfdd9ddbaed505370e4b7054ada267efee4b38acb2eede584efc776ca12ef90e 103 main/binary-mips/Release 15974180876dca292aa33a93bf4712c579e48a50842020fc9fbb5bf6185bebe6 37340330 main/binary-mips64el/Packages d7723c2e3a0d4931f22dcac54bbcedc697b22b5cf0bb690216acfefd4f69944b 27910 main/binary-mips64el/Packages.diff/Index 32dff20bc482f0a3a2e7117c9b31908985c7da4065a610327e9d04c3bebcc712 9156063 main/binary-mips64el/Packages.gz a5fe219c492a1d1af2e9e617c7a16c962f7fc8fdc99fadfd8e786349beac525f 6834608 main/binary-mips64el/Packages.xz a3135889946204b9cdb22c8f2f435e566f1fd941606a6666b0297adc3a8baae4 107 main/binary-mips64el/Release 40f282635f2bde397acaf3e76112306552adee959c01c804173dc81a6c4564c5 37668023 main/binary-mipsel/Packages f6614536a8dca5f0c5e181cf2e60739327693573ac5ea20f33805ca96409bfde 27910 main/binary-mipsel/Packages.diff/Index 2e03fbe6ff2d29d7c3e20ba5b50f1a172c5dbe708d1b9d5b3bb5ec7f49acad40 9262851 main/binary-mipsel/Packages.gz 1e5d0eed7c2582cd21a58d5db2a6bdde2c1ba62c5c88a68665a06a64e32fcdee 6912400 main/binary-mipsel/Packages.xz a4c0b9ba49c406bfdb0d564e7daaf8b2d4e0cf978ca37b2981fc970d68557dcb 105 main/binary-mipsel/Release 3e600b48258b911254f8e12d2eba516f0c86bb6cb66bd07afdb1a222dd6e59c2 37823973 main/binary-powerpc/Packages 8ddf615b5f1b079258803a4fafbaec237ea62a6f9095383a7092320b82bc43de 27910 main/binary-powerpc/Packages.diff/Index 43896af9beb88d69a64e1f97aed98f2b8a383ae8b102e23414afc6638a98427a 9292207 main/binary-powerpc/Packages.gz 6d69e6f6a2fd87ce8f704e3368f92a054a2b52c2457ec69cf363789e24626435 6929276 main/binary-powerpc/Packages.xz e58934ec639194e73fefb1d44b0bf5866adce147652d74126c5f401691241e6d 106 main/binary-powerpc/Release 43996548337ad75ef7a404d90fd1d32376882559ff019f78012e71b1ac64d83d 37859587 main/binary-ppc64el/Packages 3515efeaa92655d1c1a0ffe582b21db9fa288afc425b69a4e9f4c474817aa857 27910 main/binary-ppc64el/Packages.diff/Index df0bce791228021b5c44e31ec8256625627cf1ecab2d747e3fe1bc6877051b87 9277244 main/binary-ppc64el/Packages.gz 3c85bc4f712205f3445b4421068a98eb69f203abcd4601efc659eaa1bcb8416b 6921148 main/binary-ppc64el/Packages.xz 29eaee9b665539956ef860f083f3885b3d69145a8c9bd33dba701039a2c46e00 106 main/binary-ppc64el/Release 7e26f1ac0fc0a166e1db5702246cba50ae918855b5ec8fa7272ba231e018a5af 37432240 main/binary-s390x/Packages a76c3178898c41ff2d7a9e95a5a105bce1ee7bcf564824ced543abc06990ec23 27910 main/binary-s390x/Packages.diff/Index da4b84c571306ffd758aae45b48037168fc87f8d15842174970266bbdb807631 9217612 main/binary-s390x/Packages.gz 69d9a47f563df54153c018c0f2f705248a97bed26971c981aae34780de38d69f 6875604 main/binary-s390x/Packages.xz d9226f019e4de7c67111161156d98d7bff3eb72164e69532c0e9066b2a625f7c 104 main/binary-s390x/Release 19dcb29f8d2240f8e95dbd97b1dcd1ac1ed7429f906f4f2ac6c929fa4c42fb25 63066 main/debian-installer/binary-all/Packages ff8347481ac62bd1a14c89640b3c65e753b07d734b2747b2baa1350bdc066ed7 16829 main/debian-installer/binary-all/Packages.gz 2769d338207e4fbfaf84e9ad4ad2e39cb52940cb154529152295175e86f24034 14836 main/debian-installer/binary-all/Packages.xz 426d4a8e95369e5d97171b4e8e5dd73a1039231d256e35cfd223bf572be116ed 102 main/debian-installer/binary-all/Release eafb7d2b5be831f402929d6aadafd785db65240cd471782e08694c2b78b3b00e 258901 main/debian-installer/binary-amd64/Packages adf69b6aa09e4df452c71acca288349159c3cf8309912aaeb1886b784471f331 65129 main/debian-installer/binary-amd64/Packages.gz 055f2922bdddab4bc5c0e0b72c1835c6f657c2dcbae8add4f85fe5862e3557bd 54808 main/debian-installer/binary-amd64/Packages.xz 07cb692d133dce21dabb9e42201b8e632a7c6a069b53f9ae8173a4ea24606da9 104 main/debian-installer/binary-amd64/Release b831881dba6b4a110a45450f7e8f6ebae2d700db99fe3c5444674a1e4eda6de3 239565 main/debian-installer/binary-arm64/Packages 50b92d50e650200ccd609893a9718db46ff78c65ca4668450a7efbbe32fa795e 61678 main/debian-installer/binary-arm64/Packages.gz e936937fba91eeb63e66703cf817a8b9c65024f49e7fa86f25f7f4639b33d78d 52152 main/debian-installer/binary-arm64/Packages.xz 16b43705f8420470a43f96954eb7d00a75c4408a36c1b86ccf2bd6cfa4ebfd98 104 main/debian-installer/binary-arm64/Release ce5a93085e974dab2deb0da4cca6e5d0858d76bf310811dcf5370bef20883861 277695 main/debian-installer/binary-armel/Packages 5a44faeca117a93ab177834d891e43263345c213b8c08a822c08cb02151f8bcb 67415 main/debian-installer/binary-armel/Packages.gz db01006a7f689c09f0a451c73a15bc93a4c2d4278c7f5492e70691a02de7200c 56652 main/debian-installer/binary-armel/Packages.xz 82b62056193684651c2bf9ceb2af527cc75d034576d4cb3bc9b2f95fabf93e8b 104 main/debian-installer/binary-armel/Release d6d1f8df525dd572f9bf76d102e8c7e4e1e2ac1543662b277f4399f0817a8908 238490 main/debian-installer/binary-armhf/Packages b91d5f3c91a66cd7f55b640dec1c8a6b69379bf85eb1c98840d165289abf9bf5 61449 main/debian-installer/binary-armhf/Packages.gz e785f3eea00be33e3726b650b0f77458833d150e7ab64adb86596b21b1c39322 51968 main/debian-installer/binary-armhf/Packages.xz bde8b39b284457d38e4af1f04f9de8e73a8705795de39525a6def7d42e523396 104 main/debian-installer/binary-armhf/Release 52ac986b0e26d384e51c43a2bc59afcc5736405ae1aba47ea32aead426f47821 163351 main/debian-installer/binary-hurd-i386/Packages 60540e4dc290c9d578d0a6bde73f41394cf2deaaf57930b0e889b5d1d07dba5e 44433 main/debian-installer/binary-hurd-i386/Packages.gz 3c731885a85e3ad6b43256c3597922f64f4c3568cece7a928613d9cf2bfcc56e 37804 main/debian-installer/binary-hurd-i386/Packages.xz 141c84b75fc4356d505e86c6603dfe15875c7be89f23b4e99570b97822110b67 108 main/debian-installer/binary-hurd-i386/Release 3423ee13dd694bf8ae4e612b3776ef8db21dd79b19285f3cc11f47a93007e01a 326037 main/debian-installer/binary-i386/Packages 30faeea1e84e05189cf958c17a73c779cc20bbaad5efc372ba00f0a198c4ddbe 75140 main/debian-installer/binary-i386/Packages.gz ce7f378714cb417823c41c8eb45a4ef34e9363f35e743448dc6d902fca8770b7 63056 main/debian-installer/binary-i386/Packages.xz fd5827463ef11fa7a4c0777a83766441d7a730109e012830e7ded5aa051042f6 103 main/debian-installer/binary-i386/Release 8613a8e66cec2c8ea9ecc65439cc12f7378e3c3c106200dc7b890c4e97160f0d 199536 main/debian-installer/binary-kfreebsd-amd64/Packages dd6dbe97ddd9e1b3ffd98d7bd735d138f8272d2e8150e3889d95cda89401cf6e 52052 main/debian-installer/binary-kfreebsd-amd64/Packages.gz 498d55152dbf9e3a5ffd0e16fab7d9056252f6696fbaad0965bfa5328616aded 44020 main/debian-installer/binary-kfreebsd-amd64/Packages.xz e9cb26effa2842679d46dea78abf7662b5a75320e0dcf15054164abee90df89e 113 main/debian-installer/binary-kfreebsd-amd64/Release c568de8a747cdb5f9287b5a00e44363e97c8d4663fc45290b517a2a593978d7a 198799 main/debian-installer/binary-kfreebsd-i386/Packages 4d91b1cf5d13db9906a0db7346f6c5ea8f3faaf5ae843042804b1092801e8953 51848 main/debian-installer/binary-kfreebsd-i386/Packages.gz 88d289b4910806a472adf4d5d40a60e39753c3a5a42a4fca7e1c14ac5c5ebfec 43944 main/debian-installer/binary-kfreebsd-i386/Packages.xz 0f5494dc8749cf8141c7f288273c275f7ee50c1b37231418f1db376bb7478b83 112 main/debian-installer/binary-kfreebsd-i386/Release 3adcece3efd312cc584c57667b5699edb31c7d9feddead3724d789b32e4caed8 299343 main/debian-installer/binary-mips/Packages 80a6228f3e5e5c4378f3ca3c4a065f7eae13eb071714f58f54f71334acd7a022 70317 main/debian-installer/binary-mips/Packages.gz 762c50cd552ee6628629909f708b393f56a9be0ef84fe8658fb8f74f19e8d875 59428 main/debian-installer/binary-mips/Packages.xz cfdd9ddbaed505370e4b7054ada267efee4b38acb2eede584efc776ca12ef90e 103 main/debian-installer/binary-mips/Release 3588c6735e797fb410181a416097ba26ce3c2b0675f3037affb9ab93da0e12f1 360842 main/debian-installer/binary-mips64el/Packages 981fefa3728b93c4e3eda7521abac6989aad11c9090735bcece2a46de503e986 78622 main/debian-installer/binary-mips64el/Packages.gz fff6dd8faa5927586778322723ec384934c13a667e5f45f3cf1065b707747b20 66228 main/debian-installer/binary-mips64el/Packages.xz a3135889946204b9cdb22c8f2f435e566f1fd941606a6666b0297adc3a8baae4 107 main/debian-installer/binary-mips64el/Release e96f583adc4d9cae787b291996c74b740db483e5871ff8504e8fba9f4a975d87 479718 main/debian-installer/binary-mipsel/Packages 8cecff99689c71462f9fa5aed2e97a69ad62a692cfb607691fc853569ae5a8a2 94984 main/debian-installer/binary-mipsel/Packages.gz dd256973f6444cb4089638b8c5ab025c7ce404ddbb7029c7eadb3057b25d0231 80008 main/debian-installer/binary-mipsel/Packages.xz a4c0b9ba49c406bfdb0d564e7daaf8b2d4e0cf978ca37b2981fc970d68557dcb 105 main/debian-installer/binary-mipsel/Release a1b098e7265ddd02ead590a9bfbbc917b7605a0bb396095f389e4a08e99bec3c 310055 main/debian-installer/binary-powerpc/Packages ff2364ff0722a2948e83f377fabcd8561a39943c268e44f908d0e85bbf8a043d 72594 main/debian-installer/binary-powerpc/Packages.gz 56a27b1cab18acf6c50b1df79f299a2baba2ef7732c5fe290839b651096188e9 60748 main/debian-installer/binary-powerpc/Packages.xz e58934ec639194e73fefb1d44b0bf5866adce147652d74126c5f401691241e6d 106 main/debian-installer/binary-powerpc/Release 846c39a7755ffd13d3094e4de6ede4d5e06ff5ceb46a98ebd28eb53a1a5ffc12 241368 main/debian-installer/binary-ppc64el/Packages ba016a2b69af3eb52bed2e210009916e184ed2498cc2a1ea4377563dedad380d 61537 main/debian-installer/binary-ppc64el/Packages.gz 04480266634949d89e97fbc59afdb07962e8be21ca14e115c1926a556048c1f9 51868 main/debian-installer/binary-ppc64el/Packages.xz 29eaee9b665539956ef860f083f3885b3d69145a8c9bd33dba701039a2c46e00 106 main/debian-installer/binary-ppc64el/Release fbec413dc2c1fbe272e53fba5517a6d5075119217c938a5f4af5ce223e030421 217996 main/debian-installer/binary-s390x/Packages 2d636884fb244098b0d73a122feeaa340ab1ab05115e45e0b3c69c3ced77b667 58135 main/debian-installer/binary-s390x/Packages.gz 3c0555582da6a91b1751c5f5e631d5f07fc31d981c7034fcef0be6d259900439 48892 main/debian-installer/binary-s390x/Packages.xz d9226f019e4de7c67111161156d98d7bff3eb72164e69532c0e9066b2a625f7c 104 main/debian-installer/binary-s390x/Release 2b6add80d68dc7c65a6f404e2fa5ea35bd2b418b332c070ffacd554e73a9416b 7796441 main/dep11/Components-amd64.yml 2867e0d90c64568e2a25c371546c9c04a01dc14f549620525c9c3e9d1870b8bb 2854073 main/dep11/Components-amd64.yml.gz fa51b492af02b7540e084b9b363a0635e6387a54f6f4f9fe45992de0295dc6ab 1850876 main/dep11/Components-amd64.yml.xz a668a7255f4a68a8026dbe8c33dc662bf65fd7da79d44cf7e1517e34d5322293 7735559 main/dep11/Components-arm64.yml 744e29258913f71ec0cbc2090f6f0eeb819c7d19958778d7c585c23cb3002366 2835371 main/dep11/Components-arm64.yml.gz 19c48720dfda940ece0476a634f35df9372d69a590ee7675a39058aaa34cb6fe 1839368 main/dep11/Components-arm64.yml.xz 6920470671875e0f9a18363b95eef8863afba0d33497edfe0a3a9fb17d6f6550 7744621 main/dep11/Components-armel.yml 28ebd252d9e9b875e60dbe30a542111decd4fb6c043938d75f32bc7c3b802d08 2837621 main/dep11/Components-armel.yml.gz 04d403c5cc79c1333bc3db39b2becbe786d4257a25fdb3a795de2e92baca4ec8 1840304 main/dep11/Components-armel.yml.xz 6bf47cb36757a7b19972cd7151fc2b4c55c2eb077d30fc19103c08410184f19c 7753412 main/dep11/Components-armhf.yml 7aa5a9da1c7ea0a0009d83052bd37bc0f6c8741f4a83e9f956a71d8e8f4d1a04 2838544 main/dep11/Components-armhf.yml.gz c75953362cfc75ab475bbef98e717ad653380065bc1a7b015f39e5fd6ccdf6e1 1842132 main/dep11/Components-armhf.yml.xz 48ba32b1c10b41f4b28bad40de687da7fba63ebb782d580b656509d30aa3b969 7795011 main/dep11/Components-i386.yml ac60bd291efdc7cebb782189c0331586362b15f118c3f36662fa3b79d46354f5 2853321 main/dep11/Components-i386.yml.gz e565ee62f2ebb7a23e7f7de3d28332d254ef910f21b92ec8523ac0f498d016f8 1850760 main/dep11/Components-i386.yml.xz af46dc64347af15c1a48d605fd5d05438862ad606e5bf37c4cb594499787eb2d 7285280 main/dep11/Components-kfreebsd-amd64.yml eb85a70159fb91a20a5a102b644d8b08d24178b969eef1f5be4f688565ff530f 2669347 main/dep11/Components-kfreebsd-amd64.yml.gz 986203b8bca15bb92fbc61654cc7d0095f5a120a8210768dbc824061b98dbe0a 1732772 main/dep11/Components-kfreebsd-amd64.yml.xz 48aa792031f676e2948dbdd75619b5f445579b6fa4db1585f18bcfa55ce3a869 7747672 main/dep11/Components-powerpc.yml c97308a0897ca0035768fb7dd7c0ee2ef8982cc319572b6805524ff11ae0ad04 2838839 main/dep11/Components-powerpc.yml.gz a56885af1975a131836d7284158641efd0db99244080b31628e67a877d4342de 1841208 main/dep11/Components-powerpc.yml.xz ed7ab3be19dd7946d75807813d3d809fd597d7330da6229b92a8559c82d4e564 17068032 main/dep11/icons-128x128.tar 3926d53c6478a1144dae0c05fcf2655850f35cc10b17403a625021aa38a86448 15132129 main/dep11/icons-128x128.tar.gz 1284747ddbfad7092ee234d0f605d57ebe41c96b63e152f9da469d8ec738a5a5 8170496 main/dep11/icons-64x64.tar b39ed190c7e14931a1b5087d27b6caadeef5df7633691ef74920d13c45b54e65 6466066 main/dep11/icons-64x64.tar.gz 1e374870b76e80b982d14e26dfa0f8c6ee2aad8e39e50721cb0f9f8ad28a8a8d 8628 main/i18n/Translation-ca cd2cac5de40e25a1db1d4bbf9e43ce8a29923844b12383aa985b8db2cfbd7774 3543 main/i18n/Translation-ca.bz2 aa8e6e1d8e47de43b9469a8a3eff30a33559a20548949b40c352b420ecaade8c 1755527 main/i18n/Translation-cs 3d066b1c89a7ae5310f6e63824e58abc4b02988f11af134128d81e7be078ab29 456958 main/i18n/Translation-cs.bz2 2f278e7384dc57159e39fadbac82d94604b1a3ab8985c4da4d8cb3d2681c42df 14512 main/i18n/Translation-cs.diff/Index 3072be9daac7708d563f054e71759ab8653a793cb1b0e019548f29a0c5cf7ddf 17190796 main/i18n/Translation-da a07ae07160c3d3901b3866eb5dd02529ba9a03e225410e23b928d3e36c482915 3716728 main/i18n/Translation-da.bz2 918c8bb270ee2f667eb8c0e62aca9bef4fffe6afd6a40f959060219f7c134511 27910 main/i18n/Translation-da.diff/Index ceaec3203741359390d48d864486fab638196da908266e9e64558fc8b0c59ab9 7563488 main/i18n/Translation-de f117b1a1c2b3c7ee5dee0e5e618efb05edf354931966554bd38244312201fbea 1724541 main/i18n/Translation-de.bz2 9efc4bbcf325f3ca872b72bbb664bd682ffc7c7503f7ee42d2a5f7da34872dec 27304 main/i18n/Translation-de.diff/Index 284169348b8bd4e0de4cc5641eeb05577e80d2bd736452e454976c052cf3cbe2 1347 main/i18n/Translation-de_DE 481a435ad350105b74c4972859c44f447b7a8b5edea0d42f6dd635792e00a461 830 main/i18n/Translation-de_DE.bz2 9f9abe444c71a7c8c9541f626211c000e4f311c8ea0a9061ff125c53ce18a210 8287 main/i18n/Translation-el 8e4906ba999712818c7839947cfcd30d3575e7e6462d7c3c2a230f9ce84defc0 1896 main/i18n/Translation-el.bz2 973cac2647ea8e439c6f7b2b474d1d7b6c0847df2f261e96546a4f88337843db 27076273 main/i18n/Translation-en b04cd0855aaf3f70d76ce378b1c508a3d5945f4e630e78c5f4ce4c32408127d9 5427424 main/i18n/Translation-en.bz2 e422327bd3382f40cc0b29283106fb1d3eaf17df7b59dac808f63a654aef85db 27910 main/i18n/Translation-en.diff/Index 847690699f812c7d0e3f424aea63dbe176a0a5d4038a02e9aae5f27850b2ec81 2517 main/i18n/Translation-eo ac072915bffd0f6a205f28dea821a070c349af7bf4b65b4179aa0a915bbbf08b 1279 main/i18n/Translation-eo.bz2 4095465f33a6bd62ad5d5cc9c4f85b12fdf6530aa37dde9f2a974bc2258b8a1e 1326503 main/i18n/Translation-es 45a1921e999a7757933d302d99439ebf5a89f1027ab6cbf6fa1b6a36ff68093e 323379 main/i18n/Translation-es.bz2 3d5c2442fc311560e27bab4a69d8827573ef7864f9b6e038fdab7cb229918b48 17464 main/i18n/Translation-es.diff/Index 50f69276ee42d67f783d4ed8ab93fde3af4cd1b46cf826fbf39cc77b38ad919f 14383 main/i18n/Translation-eu 912db71591f0bfbddbb59bce6d757dd27d72ea3f56eb8e2397cb6c41607e2d72 5475 main/i18n/Translation-eu.bz2 18f79c4119f514ce2ed2a4af62bb547d249881125869202dc8454693e30c8c1e 736 main/i18n/Translation-eu.diff/Index 0bac49d589ae73bfeb86d62d3d633f2ee29b7d689828512781df171b86f970ab 386506 main/i18n/Translation-fi 7ba714ae1b6a2a0ac7c76727d01d598c0f7f3208ffb558e7cb2a7d92ce2152f6 106618 main/i18n/Translation-fi.bz2 c88bc10f4d96bb82cdc9f48940e177f3bffc81af2f0229a557f5424556a838a7 11068 main/i18n/Translation-fi.diff/Index ac779bed66162a7bab1d95c119a7e849043f9b38bffe19ac30f92c8b8e2ce16a 7401641 main/i18n/Translation-fr 948c03e5e34aa7ce88caeadc5874b9bc76666d4cb88d30955a802afe287be488 1518856 main/i18n/Translation-fr.bz2 a3ebcdc75aaed293be328248934f9d26797e7171768c6a1b1d07a227d9992fe6 27796 main/i18n/Translation-fr.diff/Index 5ab03ce3f511cbb5a361ea64ce89e7ba49e01f651fa2e1d4af3a0b10021c3689 21899 main/i18n/Translation-hr 033b8b7b0246dc1d6c75df3abcb236960df570f8c04b7bf3a29e748a3de0434c 5692 main/i18n/Translation-hr.bz2 ab2f5608641965715b677ac5fbc57bc42031154632b02954947f9aed996821bc 2212 main/i18n/Translation-hr.diff/Index 89bfe0cad2885305d5d1af0c78a1b7f18994185b8f60480c0107d81ce1f34438 96810 main/i18n/Translation-hu c3716593bdb1f60488da35fe48e786423e02a24f782aae023e65fbd3154112b7 31851 main/i18n/Translation-hu.bz2 c8bafbe9e089ff8a94b0e86da15b485ac71235a068fd9ba628d89916b8348da9 1720 main/i18n/Translation-hu.diff/Index 0aaf5db67afdf995c5a728194e9715d26a2044ebd50cc5fa022c2371a4d85513 7124 main/i18n/Translation-id 6fcfabedeec60499786b609af2e7154c20307931e976cd2cda4bbf909ea1c6f8 2899 main/i18n/Translation-id.bz2 46d5a128baa65a889e5cb5a43fdb837fa612cc1240c381b57b1deb578aae7e68 21789753 main/i18n/Translation-it b01eb20d0522d2d1e23c493af214975ea598d9ad4d08a019d0715e2b31dcc822 4268806 main/i18n/Translation-it.bz2 c7c1db21789f0d522822accc7759a421cfee797db9ff8cbc92514ed5b85d8079 27910 main/i18n/Translation-it.diff/Index d774a6cf0f8d3506b605cfb21737bdb7fb8d03aa5defde3ea8a0f91f5eeecfd0 5075815 main/i18n/Translation-ja e4ffc9dbe6437620f8f2311920cd8f6b1a2e00d1aaca64ed4437d7ef12e090c6 913629 main/i18n/Translation-ja.bz2 650a491c720acf9cce36a88819e589e9900b550804c592de03b7e4ec75e08ab4 27304 main/i18n/Translation-ja.diff/Index c4f1d19666e0750e947499a33d16ca76049d21d460e309ef232172b336217c14 19077 main/i18n/Translation-km 69632d98e66c1a7056d963ca6a018984ddc28d430c04988900198c48396aa73a 3407 main/i18n/Translation-km.bz2 5960f70ed862adfc8184ac6717bdd0c309fb88dfc2f515624c7c55379baf9fb9 1720 main/i18n/Translation-km.diff/Index b6ef66cf3a04d86c92f8a626603c49a1b8bbbc0510947f397c6e61a28dccc0f6 1631004 main/i18n/Translation-ko 5b29de7d451e521a6d34e58f9cf1260fc911036dc899df721ecc08ed69b141d2 348522 main/i18n/Translation-ko.bz2 da026ac56e180d0d6a5cc209f973c4f79307d7c600d1e25be818ebe61c6accfb 22876 main/i18n/Translation-ko.diff/Index e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/i18n/Translation-ml d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 main/i18n/Translation-ml.bz2 917a62d4d2bd8fb889d77caae2e4ff39abb23410919ecdc553e8aa4f1854da36 2325 main/i18n/Translation-nb 487379711cdb467cfdc7ff412a0a844796bc8371252b051fc1b325f9ac90832d 1302 main/i18n/Translation-nb.bz2 55cd046521e8af3db8dc99c8ed1efaa7d90ebf901c2a507eb0fe59d3a7cf815f 264671 main/i18n/Translation-nl b0b66f8e47c921744974f857f50710f749872a89e60c7f5be62dcbcc255b6ebe 71487 main/i18n/Translation-nl.bz2 1e2c3990e5a3e7bd37bd6e0d14acd1cbd967e4823efb8cbea827283c68d5d95e 9100 main/i18n/Translation-nl.diff/Index 3d3304429734bb7fc3a6c2d2ae96c18fab0915085f91029526101d4e37a7c7ce 2458040 main/i18n/Translation-pl 9f70c5b1bb9fa6dd8134fc38347e4fcf87397974fd1fa04ba30cfc4934554954 569778 main/i18n/Translation-pl.bz2 1e65e5ec83def88ece96e0874fd7e4804786bc865ea350c1cd5c00871aae2e3f 26812 main/i18n/Translation-pl.diff/Index 5be72155cee0b61542ef0adef00ccee2cb5c00094f5651f9e56971586aedd27c 1564381 main/i18n/Translation-pt 8780f320a4ee72a1b3e39026ac64de1568be9999afbb796e72fe513f0ade6a81 386197 main/i18n/Translation-pt.bz2 a1d7fbb28d9e029a7d57db8f8f86b5b9aa826f4ff63cba6ae74b2333cf13a02f 15988 main/i18n/Translation-pt.diff/Index 9d6de6b8b961fe637efee092cf10ca8d92afe0b3571b037fa48689d690451a8c 3548094 main/i18n/Translation-pt_BR aa3dcdadc481f7151650509242ee91aa57d8d8197fed2a30c8e8723d9e5774ef 846754 main/i18n/Translation-pt_BR.bz2 86afd411cd5d8f3aa32e4cecdc7cdc40b8ec23070f0f772ee37d491d7c54b2ec 26812 main/i18n/Translation-pt_BR.diff/Index e7ab43bbc80d3424f08ec3e14ec6219b7bbf86a201b3bf719393a578ab064ea9 2710 main/i18n/Translation-ro cbc7eed8d01c12cb9bb5b551548780739136155c80f26a09b26ec2ced71a387f 1374 main/i18n/Translation-ro.bz2 2c7e2ecb4b65ac45271c34fac0f83eb1c0da0c5393ea202d54e548a7bc37828d 2655478 main/i18n/Translation-ru a19a3c21f9de6314f40158d9b073b0a18ad3c31c30e6e8fc605f14c588314001 431543 main/i18n/Translation-ru.bz2 50ccac5b40920038d458dda1344d5dcc1889471768ae04deeac0d9c5d85f7e38 21400 main/i18n/Translation-ru.diff/Index 8c84a061195c975076d6eac43cbddae7534f6a62b0347cd7c73b504117e02072 3819007 main/i18n/Translation-sk 47a5c04cd83b4a89abcdfdb6eb3b76c934c6a7316959f1b8cbc7b460ee65344a 843783 main/i18n/Translation-sk.bz2 d25e6d70fa015847a12e46074f4b3977a85f8d179062677010c166868284ef35 27796 main/i18n/Translation-sk.diff/Index 5b666d5bc1f0f15eb08f62db37b2f53094aaf566f428b8ada5dd82ee51b05a7b 441964 main/i18n/Translation-sr d6d2bc3af088d4e71653201d6aa27a519775151c3f4faa24f222115b8461370a 78350 main/i18n/Translation-sr.bz2 0179ee9a35260e64b728ad2a09fa20896873ab9bcdadec86b5afb49a905d3347 8608 main/i18n/Translation-sr.diff/Index e4ec2a2b1d90acddb652afe05eb48a53f0661d7238d5e28e2f4fae32c87c4dd8 117165 main/i18n/Translation-sv a5d616f8d207af0da3891952bbee93079daf1f1b3c447724959724000501618b 36066 main/i18n/Translation-sv.bz2 92d7c8c8e4acfcca816e1c1272b17540d051f51a5d42c4219e31cabaa01621e1 3196 main/i18n/Translation-sv.diff/Index 926b4a85b107381c03f2ae77007d2a9e628b1da209a654ad190d720adfbdd546 902 main/i18n/Translation-tr b53b66bec94d548702370107afb1cec937abbd7b5b29ed47e5f64c1f7416414d 530 main/i18n/Translation-tr.bz2 409e387d4dc4cc0bc2f9d74e5d2bef262521425a3f2e4a07e549e92c1bdda5d9 4277439 main/i18n/Translation-uk c90f7bdb85fc0ad529b8865e71fa1da6118ea6eef51622132a90dc51ba6e8c24 669553 main/i18n/Translation-uk.bz2 346220e4eafd56d14d3b4485fd16d050d3799628425a00c97e67c97f93eaec44 22384 main/i18n/Translation-uk.diff/Index d7d16a522f46156ee04a92b716ba33dbb79c95bba4f349cad33ca2766c938b5a 30443 main/i18n/Translation-vi c9cd3fbdc76e5a9ea0b8d77cc54e952041301240158bab996c3fb66b4ae23b86 8837 main/i18n/Translation-vi.bz2 7d2c34fba22297c19cf1b9d7787ae5ff29afa74285df315d6b7f7a19c92f6ff0 2212 main/i18n/Translation-vi.diff/Index ba5bf385ecf4799de85e8ab873c233fe0478bbdd30611baf528aea51ae2b97d2 2799 main/i18n/Translation-zh ebb2e1910c3096f393f46f4fb6b1316e571d805d654c2d97d0ea92ddb2229424 1526 main/i18n/Translation-zh.bz2 300fa6cb66272ff4249883cd05c5435b9a72bb741a30bb3c12e21f4122b08844 334563 main/i18n/Translation-zh_CN a186649a78aa62e308065744c3c1a26ee237eaa7ae92357aed5786dbbd6ff1f3 92636 main/i18n/Translation-zh_CN.bz2 f88dde02c66fa5c190e86d2a8281c5978405ed8de1615baa00d0fa0ea0890577 7132 main/i18n/Translation-zh_CN.diff/Index 52f67312742d998a09bb592592ccf88ef07fbf75c9fef0b4aca794dc8a59249b 57122 main/i18n/Translation-zh_TW 768d5096de38af7c27a732e3d2bb562c3fb510ea4069fcfea01d92698eeee378 20289 main/i18n/Translation-zh_TW.bz2 3693b3534f95bc8809d67a670cdd0d6a6efd1319de1cb1b14215a20807970940 3196 main/i18n/Translation-zh_TW.diff/Index 782fc37c049313ea581c76d8a06d10d894532edd954b2ca85bd0197b3c30dad1 53815 main/installer-amd64/20150422/images/MD5SUMS 17abd745a3e8d79d4bc22dd9f5bded89b1841b7b991eaaf4a105bcfcc835294d 72131 main/installer-amd64/20150422/images/SHA256SUMS e6cfbb7c170fdb53bffe819a90dc0fde4dc2728b37448aac3d3beb595dfc8cb5 53815 main/installer-amd64/20150718/images/MD5SUMS dcfdf871d5d2eb5802c7a9dd2a6dfa09988be610970117c0bb807e4aad0e2478 72131 main/installer-amd64/20150718/images/SHA256SUMS 2dad7cc647954c125cb01aefe3ea660864b1ddc0bd02a3cca240bd7cec3f827b 53815 main/installer-amd64/20150813/images/MD5SUMS 8abab8a8180c02ca3225cc5cdafade4536555759b2b349bd04be1343e9b9a572 72131 main/installer-amd64/20150813/images/SHA256SUMS 09d6149410e83610406431483b528548a58ffe55eef35e416aa2d6c645eb48f5 53635 main/installer-amd64/20150828/images/MD5SUMS 15bebe8a9eadbad640a1fe31f92132b1410e982cf36710ff5b4c4788105f404a 71887 main/installer-amd64/20150828/images/SHA256SUMS 00fba993c2b9a0495fe010cd6519960c271d7a21b424b4b57677bf23b3173719 53635 main/installer-amd64/20150911/images/MD5SUMS 6564ab007ba57e368cf4e27ceb35903eb4e001f7a13fa41ce7fa3c2d21881bec 71887 main/installer-amd64/20150911/images/SHA256SUMS 1982d9bcd3e4df5c4a0ddb8b8a3be4a79cd85ff8379eb78eaf92c0000fd8a643 53727 main/installer-amd64/20151023/images/MD5SUMS 439922d81867c0a1326d2b4918e9e63cf3e083c8eee8e619eafefc1430863c9e 72011 main/installer-amd64/20151023/images/SHA256SUMS 719797fd52641baa145e96b9d68f796d6059e9f5917fb86cebe8ea813d92c6e1 53635 main/installer-amd64/20160101/images/MD5SUMS 9912410703383968f58d0039777da36a822541e5e298b3d62d4027155f04523a 71887 main/installer-amd64/20160101/images/SHA256SUMS 86e5b841fefc66d27c24b28df158d4563adac62d4a03803be9f8176c3c506ba8 53727 main/installer-amd64/20160106/images/MD5SUMS 5a3c5789d8e81f650063aeb81ea01c00c22ab092bde8cadf5cd1e5f57fc76802 72011 main/installer-amd64/20160106/images/SHA256SUMS 2ac430162d2a2633671508abf149f28b1a0dbe122aff8bd1f167e18f2d63a8cb 53727 main/installer-amd64/20160516+b1/images/MD5SUMS 2cca615ea20b9a6422585c9d4954285b41f33b095570ab7fdde096d767059113 72011 main/installer-amd64/20160516+b1/images/SHA256SUMS 23d12f98b74561addd40c415c2a4b63e55eb9ec2d1966c3a544844f5522f1f3a 53727 main/installer-amd64/20160516/images/MD5SUMS d4fee70a41229548ffb8a521bdec7a9427de2f1747d575a434590ee6eada0830 72011 main/installer-amd64/20160516/images/SHA256SUMS 9ba4360e882bd35893b6051cc04da1ca941f599e2c75f350ee22f0c6243d66ca 53727 main/installer-amd64/20160630/images/MD5SUMS 84019019358117e95eb8506e7926f133f3fab4a5b6c171dace6120ac903700dc 72011 main/installer-amd64/20160630/images/SHA256SUMS 9ba4360e882bd35893b6051cc04da1ca941f599e2c75f350ee22f0c6243d66ca 53727 main/installer-amd64/current/images/MD5SUMS 84019019358117e95eb8506e7926f133f3fab4a5b6c171dace6120ac903700dc 72011 main/installer-amd64/current/images/SHA256SUMS 47a2f89ca82421b20984d38888d48cd5200dd676ca51a9342476bc62c812379c 19148 main/installer-arm64/20150422/images/MD5SUMS 08af7315fd23120f3e8ad1af11ac2730a455d6d3b6ed673f427ee003068adf34 25912 main/installer-arm64/20150422/images/SHA256SUMS 4abd1bda3c9a9e8f978f78624e12af33abfe4a63cdccbd5ff30a9f1776fae9ce 19221 main/installer-arm64/20150718/images/MD5SUMS 703133bbbcc9cffdb51279826bd8e9fc3a7f287e44ab95c4587d2b264ee6c905 26017 main/installer-arm64/20150718/images/SHA256SUMS 01d66d6968bdabdeedd0e81c61c0fc812c9e2ac7c216872b69f264c928c75b5e 19221 main/installer-arm64/20150813/images/MD5SUMS ddfe031101b249b46717cb1ddefc90ca1894d9940241aa001b0a62bafa984977 26017 main/installer-arm64/20150813/images/SHA256SUMS c7da876058755ab6c76e702ff0411fed9c463458986511d732d8013efb98fced 19221 main/installer-arm64/20150828/images/MD5SUMS 04aba7cb700da431614fc3cd2f6b0d9c0178c41012824a2ee868055eb3062438 26017 main/installer-arm64/20150828/images/SHA256SUMS 4854c9a6530782e68e11b1ad5feadb5a021342573aea8ca44b73f676d7f167d3 19221 main/installer-arm64/20150911/images/MD5SUMS 5ff60a0ee800fc22cfdf3d24d0776c8eb65a603ea3d2a91cf7626779218924e3 26017 main/installer-arm64/20150911/images/SHA256SUMS 28d6fb70d3135d473ad1910d1e1862b0c651cba341a44555e8517580a80163a5 19366 main/installer-arm64/20151023/images/MD5SUMS 91da9120ed291b45eee2ed227e1714050037296517a3bc7f0f5848ff2a495b41 26226 main/installer-arm64/20151023/images/SHA256SUMS d05fa6e633f69d6e5e67486c86af96c6637816a9f03449c45f231ad408d9c497 19366 main/installer-arm64/20160101/images/MD5SUMS 0ee86a9f4304295a463499cb81ad326b7a308fe3f15ed567db5455afa746fd74 26226 main/installer-arm64/20160101/images/SHA256SUMS 40219645a6c166f14761286fefebeeeeef077dfeccc375f6d703d4b9810b753e 19366 main/installer-arm64/20160106/images/MD5SUMS dada57574e0389c9a2688ecae6bdd5631d1afea4962415af9f774abd1e15a71f 26226 main/installer-arm64/20160106/images/SHA256SUMS b77a665b60cc6c563629839821b36d1d74f11c8bca932b2de2297bbbe986f601 19788 main/installer-arm64/20160516+b1/images/MD5SUMS a8dfaf96ea5fa2d086bfb2ad1308feb1a69dc99e440748c73872d1489d237abb 26840 main/installer-arm64/20160516+b1/images/SHA256SUMS 7543ef2b46b7339c2c2d654fe80753d71c67be4303cebc6068cbeecee6f0134b 19788 main/installer-arm64/20160516/images/MD5SUMS 60d321071941462dd9e2155a6b6754dd035c7c411d830f6d6181a2809c8af693 26840 main/installer-arm64/20160516/images/SHA256SUMS 19d318ff132aa6098e0eb9786a445565e64c425fd69bb1999363dd7cd9c99838 20520 main/installer-arm64/20160630/images/MD5SUMS 9ba172874b238fe47b6ced472f43a36d69727ae0acb6408c17da79f9abc03734 27892 main/installer-arm64/20160630/images/SHA256SUMS 19d318ff132aa6098e0eb9786a445565e64c425fd69bb1999363dd7cd9c99838 20520 main/installer-arm64/current/images/MD5SUMS 9ba172874b238fe47b6ced472f43a36d69727ae0acb6408c17da79f9abc03734 27892 main/installer-arm64/current/images/SHA256SUMS fdbf3f1cd1be6e4192103e2af7e0d7df528af5c3786fd04f5ccf4ed9dc47529a 8985 main/installer-armel/20150422/images/MD5SUMS 8a5e9f96a5574c8082ff1949b77a49b97593274fb4ee9d188609b2c849d534c1 12645 main/installer-armel/20150422/images/SHA256SUMS 248531e71eb0a18d89923b0374550811453fa5cef8779fc49cc8b0d86b3563b7 10136 main/installer-armel/20150718/images/MD5SUMS ea5743f8661e7273e111597ea888031b6532c83a6649bd69ed6f165f392a039e 14244 main/installer-armel/20150718/images/SHA256SUMS 2dc35a8a631ecf115d01255353b932b8fd82aa6605683685c46e1ff49ff5840e 10214 main/installer-armel/20150813/images/MD5SUMS 5967ca0fba0bb9558193009f7d4778c13cc3fc47b5a55b0589185b7b55a92e21 14354 main/installer-armel/20150813/images/SHA256SUMS d28c0cbb8fa24ea558f1072bd690b4a3dcbc053ab565aed9bd28aa83a36fbafa 10214 main/installer-armel/20150828/images/MD5SUMS 7d08a5c7d823980aeee48df7ec5e69af33b32da758e71b45d18b4e2bf4a88946 14354 main/installer-armel/20150828/images/SHA256SUMS 1ed3e386fb662287f943c27bedf0befca540507b4654948705e036c48d53b6c6 10214 main/installer-armel/20150911/images/MD5SUMS 8ebf74083a551d294208263250f232ca13f38b13ed9e60fc4234d7b06653dbb5 14354 main/installer-armel/20150911/images/SHA256SUMS 968a647886f71779e844ff141d6ad19d4ff800080842deac1b0cbb1e8688e1be 10214 main/installer-armel/20151023/images/MD5SUMS fb9e14b2d95861331c561b450126182d892322d35a9b1b0bf9cfe53c760693c1 14354 main/installer-armel/20151023/images/SHA256SUMS e732991de54c567276f722af50167bca737f3a6bce69155779109826bb7dd231 11320 main/installer-armel/20160101/images/MD5SUMS 109999ccf0974ea3ecce3b0b4d3100dc9a4617cef6df278ccb52f64198e2d6b5 15908 main/installer-armel/20160101/images/SHA256SUMS eb3941390e4aaafe57e88ecd25081d3995de940fe14988e8ea49c3a769961516 11320 main/installer-armel/20160106/images/MD5SUMS 469bcb1a044fc4b58f19d1e44cfdfea0f3a723f7ee2c8d3ec23ee5177d86ced6 15908 main/installer-armel/20160106/images/SHA256SUMS e25e5c6603f7e3e279957c7fa029ab00a574143a7e85dcc1a15250dd5c3e74bd 21918 main/installer-armel/20160516+b1/images/MD5SUMS 9fea0634b1dbdbc167a16234d9ad980f2675c70a3fb0c69670c2e5a9ee516a2a 30634 main/installer-armel/20160516+b1/images/SHA256SUMS a35016c77831e5757c8f56634ba1cf04eb317fd927f4d9303f509ca9f2aa2799 21918 main/installer-armel/20160516/images/MD5SUMS 8c317f5898b8af5b21d17f33945d629c5a5c9d9a00f7d7620421591afa89f572 30634 main/installer-armel/20160516/images/SHA256SUMS 7876a5c20d292f8b54d42398a85ccec97984f9c84cb159684f641719ce37a57a 22683 main/installer-armel/20160630/images/MD5SUMS e611bef6f697250244aaa2d99f915b287e2316e048a011234723f9e93f5aff4a 31687 main/installer-armel/20160630/images/SHA256SUMS 7876a5c20d292f8b54d42398a85ccec97984f9c84cb159684f641719ce37a57a 22683 main/installer-armel/current/images/MD5SUMS e611bef6f697250244aaa2d99f915b287e2316e048a011234723f9e93f5aff4a 31687 main/installer-armel/current/images/SHA256SUMS 8ed796ad892478a3d68d7d6e5ab0d4f0106a45a48a1bbd0c812474f029fde7b7 19599 main/installer-armhf/20150422/images/MD5SUMS 983d76be48052b2f1bf31cb984ec93f47468da67cbc4284288a0ed2a9a6c93ac 28379 main/installer-armhf/20150422/images/SHA256SUMS d662fd2ec159ea1b4fa3b7f2a87920434c62a5104e17a43723612f028915e615 21631 main/installer-armhf/20150718/images/MD5SUMS 130104d66e55c1da44c0a2ab3f161c72e32d81a59074987585fe67eba733199e 31339 main/installer-armhf/20150718/images/SHA256SUMS abc279bc67b5a501e02b49d224072d429132e1fd662c66d1fbb69838465afb5c 21993 main/installer-armhf/20150813/images/MD5SUMS 9dcc502decab968d2a197b16e0548d98770945b22cc2460a36ea849e821e85b9 31861 main/installer-armhf/20150813/images/SHA256SUMS 24416e54c70cf47a3833465cdc620dcd8c2981c1339fd516731f2cfb6b64e48f 21993 main/installer-armhf/20150828/images/MD5SUMS 28fb5018ad1dbc59e25f853dbc4dff064e709f1a3c61630ff73de8bd669ae05a 31861 main/installer-armhf/20150828/images/SHA256SUMS 634ba7496493b44b315e69f305cb9428101d91cd2e83a3966ea0c7fede87c277 21993 main/installer-armhf/20150911/images/MD5SUMS e739d9e0664935fefbd047ce6269aad77f08fa69442e0582353540dfb831c1e1 31861 main/installer-armhf/20150911/images/SHA256SUMS 1301b0f13d404b76ff764e1feeccafbdfe1e3c90e952374e31db294cd81c8f99 23951 main/installer-armhf/20151023/images/MD5SUMS c691189cea644d6c808ea6ebd40be096879ddea3be429ce1e8a0389f654e13fd 34683 main/installer-armhf/20151023/images/SHA256SUMS a4a46442da62a087bda4af0683aebda23e3f09ba0a0b3ea31bf0393ebc7452c1 25780 main/installer-armhf/20160101/images/MD5SUMS df3eff2db5c56ff2cca5c28f92abcd81d0ea9e934b931df5c72e37b48ee6d1ac 37312 main/installer-armhf/20160101/images/SHA256SUMS ccdb7eef05d624d0b1a35f814e9e6bf0974719fadb9de3207c0b473d0d367aa7 25780 main/installer-armhf/20160106/images/MD5SUMS b6ecd8200600151feb3ff913414b86de89a82e5c5fe16008d71bca4d57c89729 37312 main/installer-armhf/20160106/images/SHA256SUMS 59ebd429a2981cc6b5c2b4c7ac9be9a95c7c49daf4726000f351cc13612512d4 32094 main/installer-armhf/20160516+b1/images/MD5SUMS 73a2e3d2ab212e4fcb99d01bb33b4e124356abb96f668a8c094da544188fd2fd 46346 main/installer-armhf/20160516+b1/images/SHA256SUMS 36b4665344f237a0a8bd23bf02c25bb931b4690b9cbcd030ad933db204d46b99 32094 main/installer-armhf/20160516/images/MD5SUMS a1607ebc68eea6a17ff10ec23101334a6492415e78afa7daae2bbe9719c2ab63 46346 main/installer-armhf/20160516/images/SHA256SUMS 6a16f9fe1409e46adaaf6e0b5826d34e8b0ab923e64e152b5952ac980b645a06 33942 main/installer-armhf/20160630/images/MD5SUMS fb9ff4edbef6f1e57aab7d6440610665d296fdc4a94347cd5d05ad1b8f8cf7bc 49026 main/installer-armhf/20160630/images/SHA256SUMS 6a16f9fe1409e46adaaf6e0b5826d34e8b0ab923e64e152b5952ac980b645a06 33942 main/installer-armhf/current/images/MD5SUMS fb9ff4edbef6f1e57aab7d6440610665d296fdc4a94347cd5d05ad1b8f8cf7bc 49026 main/installer-armhf/current/images/SHA256SUMS 0c1498d49c3cbba310a31b29563273272237c49effb30bbb57a3e618e03bd212 52495 main/installer-i386/20150422/images/MD5SUMS 8ab3f5b9dbf85cd95ca3fdd96e47f5145f9119b2501bdb4774e9da644e74c8e6 70875 main/installer-i386/20150422/images/SHA256SUMS b9e06e30940c32ad209d1a0887f9ed81026c19eef61764a4655ceb385d88f83a 52495 main/installer-i386/20150718/images/MD5SUMS 8222f2d6c49b2d0095989b568f431358ededaeaa40bf5732139a62e4709e0e42 70875 main/installer-i386/20150718/images/SHA256SUMS bf07440ac55d9bfc367c11c5c2a3c8896a3459d9405492c197c80f4c883de294 52495 main/installer-i386/20150813/images/MD5SUMS 1574b953b136ba24ca92ee02217e14d6a8bf44e7be4034dd8abefcfeb1c0b891 70875 main/installer-i386/20150813/images/SHA256SUMS 5ceba692b7179e2ec1d230f54b8d4090f2d9e5bb6240e7ee17f64f3e72bd46e0 52317 main/installer-i386/20150828/images/MD5SUMS 27009193915c55e9f85cc49efcddfcf1c07cd2907105f499affd2555791ea927 70633 main/installer-i386/20150828/images/SHA256SUMS 860b23452d3ae00802e70f601680cf315203b7f9613869b315e74334f8286220 52317 main/installer-i386/20150911/images/MD5SUMS 1a8ed126619384b1cc1b17f4491770f4fad122879048079787cad8ea580a05e1 70633 main/installer-i386/20150911/images/SHA256SUMS a953c5bf53c29404e0bc7cd7f2e160dcc608a22d2b1e6ff88affdf23b269a419 52317 main/installer-i386/20151023/images/MD5SUMS 24f172b036aa1b8e8f7bed471fc26dea0f170bd7845e9cee82f8ad85bb42cf88 70633 main/installer-i386/20151023/images/SHA256SUMS d2cba4e3610c1370f90b98b571d18804bb0d02aa947f376b75a0a6ba48088bc8 52317 main/installer-i386/20160101/images/MD5SUMS 03d1176a02a38acb945a91acbdb1acaa689d67d2fa6068d8fd987138eb6e4cd6 70633 main/installer-i386/20160101/images/SHA256SUMS 984247e818959ef73b492040dbc086a436f0cabe200f1a29082531fe0968f4fd 52317 main/installer-i386/20160106/images/MD5SUMS 186667f8de974f70672f4996fbf2da8a5aa77d25ae513634deeb6c45d7d42637 70633 main/installer-i386/20160106/images/SHA256SUMS 3e764aaeb4af7a232ae9fbdca8494a27db81b1d03f17245e50857dbd6a63f378 52317 main/installer-i386/20160516+b1/images/MD5SUMS 240d44a903ff446d26ed77c5ca80bfc0d85e9e1d4ad7d948f639c9ede532f025 70633 main/installer-i386/20160516+b1/images/SHA256SUMS cefee1ec3c91a3c230033876786d886e6adb2bad1c91c35ca889b9c3e7b8316e 52317 main/installer-i386/20160516/images/MD5SUMS 5143b9694aa02cee9150fb01163407182775a3fb0623c910a6d77ac8380a3653 70633 main/installer-i386/20160516/images/SHA256SUMS 97fc44214ab2e0c1a347e8c8e068fffb7e5f0ba5b3f4aa4dc20f8370df3ecdd2 52317 main/installer-i386/20160630/images/MD5SUMS f0c62829db0a69164a50a4523ce82725956c8fb8092b8afe6d72db92f227204d 70633 main/installer-i386/20160630/images/SHA256SUMS 97fc44214ab2e0c1a347e8c8e068fffb7e5f0ba5b3f4aa4dc20f8370df3ecdd2 52317 main/installer-i386/current/images/MD5SUMS f0c62829db0a69164a50a4523ce82725956c8fb8092b8afe6d72db92f227204d 70633 main/installer-i386/current/images/SHA256SUMS ca6b0d3105ed0e01eaa9c71d869964866af7d1a74e0e550dadc50914a6f0e440 2147 main/installer-kfreebsd-amd64/20150422/images/MD5SUMS a9708f827bd440a9d50e70b67bf62a883028f4e7b5f3fd39d7a1b0bc608cb80b 3183 main/installer-kfreebsd-amd64/20150422/images/SHA256SUMS ca6b0d3105ed0e01eaa9c71d869964866af7d1a74e0e550dadc50914a6f0e440 2147 main/installer-kfreebsd-amd64/current/images/MD5SUMS a9708f827bd440a9d50e70b67bf62a883028f4e7b5f3fd39d7a1b0bc608cb80b 3183 main/installer-kfreebsd-amd64/current/images/SHA256SUMS 09dd35d20e440d715ca8d86f8da943339bdadcb00c0e3d39c6ff01cc0d12b115 1209 main/installer-kfreebsd-i386/20150422/images/MD5SUMS 3944b83d2056f3eabe1280e5dd736b3ed463dfd516fe97fbae88f1738472e787 1861 main/installer-kfreebsd-i386/20150422/images/SHA256SUMS 09dd35d20e440d715ca8d86f8da943339bdadcb00c0e3d39c6ff01cc0d12b115 1209 main/installer-kfreebsd-i386/current/images/MD5SUMS 3944b83d2056f3eabe1280e5dd736b3ed463dfd516fe97fbae88f1738472e787 1861 main/installer-kfreebsd-i386/current/images/SHA256SUMS 0ba9585385f7e4d35f74db8d234e14e0ad97de6c2b1e58f4335b9cb61cbf4d24 940 main/installer-mips/20150422/images/MD5SUMS 637d65df2638cb80ca893ba306af0478db47bd105b8a56a0f2fbf49c8e8b1e1d 1496 main/installer-mips/20150422/images/SHA256SUMS 479cf7017fa0df7b298f3f4d5b0b767be740418344d3c82be760fe06b2852b6e 937 main/installer-mips/20150718/images/MD5SUMS 18c2dde11a8f5b9fcba1b1f31430e3f620aad095822acbdd2b94039fda945856 1493 main/installer-mips/20150718/images/SHA256SUMS 08caa4c6d8ff9ff182df3745341244ec73db6166c5b54b2f7e2ee500781c2c67 937 main/installer-mips/20150813/images/MD5SUMS 244c15ab80d120e5d1a85dfbd6c1d8602ad4347bc0ffb5b6109cdfe052633805 1493 main/installer-mips/20150813/images/SHA256SUMS cb33e93a77e6c679ccb600961c57ec4dd6dd763ef7fedf16832b3239add292bf 413 main/installer-mips/20150828/images/MD5SUMS 9eca0151d107d37fd2de77bcdcb9e110846d34bf0d6213074ec4da1eb45a7cc9 713 main/installer-mips/20150828/images/SHA256SUMS f399f9fb84ce08f7f18caddcadd4f1400d2bcb163553b80b3ff55d71a5c383b9 413 main/installer-mips/20150911/images/MD5SUMS 096ddfc60e44386285637acf52ce251d5fbb3047423d9fa913db38fea1c3af85 713 main/installer-mips/20150911/images/SHA256SUMS 413aebd444439523c581a25a7154f43d4293e2760921d030749693f23b7d19f4 413 main/installer-mips/20151023/images/MD5SUMS 5582cb89eaca93ecef34ec67bc4c9113c2e71d2c1e561870a3affb59f9a44690 713 main/installer-mips/20151023/images/SHA256SUMS 56a3061ad3d38094cfbd8ab010dc5288b8c2a1e566cd2f8707628723341747d1 413 main/installer-mips/20160101/images/MD5SUMS eb10b5016362e98c97c32861c319ddd1f30c798a9a6376adaa940823efeacafc 713 main/installer-mips/20160101/images/SHA256SUMS b262d6441038dccd17fac968788c435503a0cef2d5a956332b094079f24f9c1a 413 main/installer-mips/20160106/images/MD5SUMS 4b4b0574f5740f643ccd799e8559fb1e85083492a4a6a7f90e8fd6b2cf99541b 713 main/installer-mips/20160106/images/SHA256SUMS 3b38f9cebd18e24de6de48c657dd775d8666a7920429db1ad8177287005574d9 413 main/installer-mips/20160516+b1/images/MD5SUMS 8599f38cae8b1723f00800d685091a85cff66b5ea146f425e62eae80a11447d6 713 main/installer-mips/20160516+b1/images/SHA256SUMS 8dc96ed1d3b977955c44afe016701e843d96d87a075e347ee9b80a054fd80723 413 main/installer-mips/20160516/images/MD5SUMS 52763e668941ee05d0ce51a1d5a5f6dbf17b0da9d4a583916a7c8aa988af1226 713 main/installer-mips/20160516/images/SHA256SUMS f91ba0adcc3852b90560336e6a189b39804c137b530ce381d0876037a732a42b 413 main/installer-mips/20160630/images/MD5SUMS 9abd37590aac598ad7baf857a0bdf8fd6313a3e9211531ffaf2bec4e818a58b8 713 main/installer-mips/20160630/images/SHA256SUMS f91ba0adcc3852b90560336e6a189b39804c137b530ce381d0876037a732a42b 413 main/installer-mips/current/images/MD5SUMS 9abd37590aac598ad7baf857a0bdf8fd6313a3e9211531ffaf2bec4e818a58b8 713 main/installer-mips/current/images/SHA256SUMS d6c364dc4ef14cc10ff0db0f30665f597417574549444c2bda4ddde8e6ba49ca 1213 main/installer-mipsel/20150422/images/MD5SUMS 07340180253b71ca03bd55ae026fdc5959741054f030a11f5646d06429211bf1 1865 main/installer-mipsel/20150422/images/SHA256SUMS 715ba5f08d71ec0b1ace75b00b8b8407649305ffaf1921ed76687b993766ed72 1208 main/installer-mipsel/20150718/images/MD5SUMS 7d28e99e99b93fdee802df82d63e78b21cca67961b3c16d9c3eda65c7e993e70 1860 main/installer-mipsel/20150718/images/SHA256SUMS 99bce7bd7b99c5d00ab6824cadd5e32c6df10e5a427bb9112b135989cc565710 1208 main/installer-mipsel/20150813/images/MD5SUMS b31e9342f01944b283d58331210f3eb88c25ff49ec5a29bfaec5ce71b9a5b187 1860 main/installer-mipsel/20150813/images/SHA256SUMS 13fb3fd0b55747d66ec2bd61ba74e2d662e8fb2edd52a56b984092467fd1649f 919 main/installer-mipsel/20150828/images/MD5SUMS 3545a766cb1aefeaa0d435d0cdd5fa9af1cc23aeb5a395f4e55888c080001c57 1443 main/installer-mipsel/20150828/images/SHA256SUMS 924c013e1d964352c4eb1d12cfd81e01908cae55ae073d4aa50eccddf2e8d654 919 main/installer-mipsel/20150911/images/MD5SUMS 7f1c0ffb58fa56aa5f2b258a3e0f21aac04fa8ae71bb860f5a528896faa44adb 1443 main/installer-mipsel/20150911/images/SHA256SUMS 32ed73342a1326d815ccfb4e0f473c49cd335270e367aeedf6ac7bd39776217d 919 main/installer-mipsel/20151023/images/MD5SUMS fcb192cb44f88b090cf57f6e71a32a8507a9bce8e78dd38121f1b38d821833f6 1443 main/installer-mipsel/20151023/images/SHA256SUMS a7887d4f550161290282cd13b44be58a4b913a5d6751bb073b5c5b5ceb01d309 919 main/installer-mipsel/20160101/images/MD5SUMS cec2bf1b643fa79f4350a1c77440bb37111fd322d017bc575ecb82a3fa822303 1443 main/installer-mipsel/20160101/images/SHA256SUMS 8027d271f23fed524c7913d7216330ec2ce8751bc1e9cdb5186a0f304ad49a2b 919 main/installer-mipsel/20160106/images/MD5SUMS cfe92ddc67c87c25fe72be025c4d7ebf7cba60ece28cc86d7f6288cfa4abb062 1443 main/installer-mipsel/20160106/images/SHA256SUMS 6ce5f3702a1d270859611405b959ea29eb46e1e6610cfc18f6ba9ad5c0536059 919 main/installer-mipsel/20160516+b1/images/MD5SUMS 089e9d9a497f28fa9338377263d311a661683f3bd914f7aab3be6a86d786dc49 1443 main/installer-mipsel/20160516+b1/images/SHA256SUMS f835b0ba7e61444a3e21b6129b7c0d4bb54194581860bd46f7a709153e377914 919 main/installer-mipsel/20160516/images/MD5SUMS a5535e9140f0d0eb03a72068afcd14bfd9dbaa5c6fe599649082f105de7b5af1 1443 main/installer-mipsel/20160516/images/SHA256SUMS d7ea52e86fa59cae164b43cd3690e70ebd55d7eddd9d2148719f704d7b5cf7ee 624 main/installer-mipsel/20160630/images/MD5SUMS 05e71fd18cfaa1a23f5da37d9e65c1fd7666dc2856b23a51b8cbed86573b8206 1020 main/installer-mipsel/20160630/images/SHA256SUMS d7ea52e86fa59cae164b43cd3690e70ebd55d7eddd9d2148719f704d7b5cf7ee 624 main/installer-mipsel/current/images/MD5SUMS 05e71fd18cfaa1a23f5da37d9e65c1fd7666dc2856b23a51b8cbed86573b8206 1020 main/installer-mipsel/current/images/SHA256SUMS db19e3daaca03a155831e9b588810291489f0e82be200fab0c4cbd36d3294efa 2128 main/installer-powerpc/20150422/images/MD5SUMS 581181933b42af5df34ae56e335184a8677aa4e4bd6d2f5a6f2566b1e84fdc4a 3292 main/installer-powerpc/20150422/images/SHA256SUMS a67e0d2e4e3c1b112c89a33936bf9b8a3d20e3c6388704986f2eb62dad1f010d 2128 main/installer-powerpc/20150718/images/MD5SUMS 32cdfecc91e1a0dc1f431165f5f7586f29e55ca86f92b178509ad9bef9939213 3292 main/installer-powerpc/20150718/images/SHA256SUMS 03490e0d4bb7ce94852f8625824fec2c5665bf2d02c9c9650ce114a118287aa8 2128 main/installer-powerpc/20150813/images/MD5SUMS cffa2b9f0f2a94155ac678c76ecbb45b29dd629e849052350b0abf696b2c07ab 3292 main/installer-powerpc/20150813/images/SHA256SUMS 1261f0d22f33c517158e013993951a21245d2e4db13af75e996f1a97c6bde862 2128 main/installer-powerpc/20150828/images/MD5SUMS 391b99eac85294f33cc51ad12950ef0096034b1e23660842212fb1b84efd93b9 3292 main/installer-powerpc/20150828/images/SHA256SUMS d7ac606026dcec95d44ebd6e9bbed7362240c89269a197936c2b2cf61893cfc7 2128 main/installer-powerpc/20150911/images/MD5SUMS c876db3c13bc9e5854c95417d33d17e5ac98539359ca903c959481a48bd9672c 3292 main/installer-powerpc/20150911/images/SHA256SUMS 2cec803c37d98d6e183f058299d974b8d60668f215766a6b8318826673327c80 2128 main/installer-powerpc/20151023/images/MD5SUMS d3e29265cacfd970d940b966920b091e8b4931b068bfa18ed442dd0e0d8cf1ba 3292 main/installer-powerpc/20151023/images/SHA256SUMS 8eccc52f6c72f4b20447b6cde843c92f7b040b5c58d45aa29c97898e1ff89943 2128 main/installer-powerpc/20160101/images/MD5SUMS fdb5399c64e383faa6aa6dc3dc2b338ec424c8550419be90e601dbcbbe4e9048 3292 main/installer-powerpc/20160101/images/SHA256SUMS 8dc188bad6d7f37ddfa5d44b356f20b80ff6fff6815a6c5c9ce2d407f79d03e0 2128 main/installer-powerpc/20160106/images/MD5SUMS 080ce2cb26e47953ff05f8ccadd35a2bbdbbbeeaba7343e144b4f2b785098e5c 3292 main/installer-powerpc/20160106/images/SHA256SUMS f7f15e409260256e009cb0e6740b66164c13c0bbfdbed6f4237bc40094ad4833 2128 main/installer-powerpc/20160516+b1/images/MD5SUMS 0c3a8b1f8b5e8793c815a00315bf2e25e122e470322d855f0658fa481b11a180 3292 main/installer-powerpc/20160516+b1/images/SHA256SUMS 3b8996b0e5085dbe4408ca3d31f95b62e52815263a2a1929a0582bc50591d8d4 2128 main/installer-powerpc/20160516/images/MD5SUMS 7b033f34b23c3bf95c247478c5bb0fcc8ef21eca01fa0558cad2932eae6e7d82 3292 main/installer-powerpc/20160516/images/SHA256SUMS ba2e8ce31f4123a4b6b87dba18ac37d559ea1334890e1220111358cff63ebcaa 2128 main/installer-powerpc/20160630/images/MD5SUMS c590b5725804fbcebd681d749722590475810f81941c485439c7d39408e7de23 3292 main/installer-powerpc/20160630/images/SHA256SUMS ba2e8ce31f4123a4b6b87dba18ac37d559ea1334890e1220111358cff63ebcaa 2128 main/installer-powerpc/current/images/MD5SUMS c590b5725804fbcebd681d749722590475810f81941c485439c7d39408e7de23 3292 main/installer-powerpc/current/images/SHA256SUMS 1ddb9a9a243149f93822c8b14e1f1ed2ef69c46c79c2cc2a01c20647346f86c6 576 main/installer-ppc64el/20150422/images/MD5SUMS 914330f644847bb5401fa3160cfe2d79e50c02e3df91bffb1085081a51db23ae 972 main/installer-ppc64el/20150422/images/SHA256SUMS 53efb5fabeba2ce336785cba4b8766744c24b23791222763a4e521a6452782b6 576 main/installer-ppc64el/20150718/images/MD5SUMS 9d9c8c331935fbfd2cd239bfc5ab3faaf7287fa0d7e8b6af6f93ee537c9d085a 972 main/installer-ppc64el/20150718/images/SHA256SUMS ee2cb4908cff721076b5b788b2899a4a6fd08fc726918ee5eacb1789a388af81 576 main/installer-ppc64el/20150813/images/MD5SUMS 721ab0e17a3ba49fc1d4a7ea787353dfb25d6695a5d18456e9638570ec08bafc 972 main/installer-ppc64el/20150813/images/SHA256SUMS 952dc2697724e20b465a9c4ec4518a530cb02153b8cf56f0e14e88dee71b523f 576 main/installer-ppc64el/20150828/images/MD5SUMS 16447ed5c7b09a2c08a7c190c071c9aaa8cb2e20b6eb99cd79aa76a3288d6f68 972 main/installer-ppc64el/20150828/images/SHA256SUMS 569ea20b8badd750fdb9b1aea748db5f2d7a8c7ea75e21714dc69b8e62c3c98a 576 main/installer-ppc64el/20150911/images/MD5SUMS 7cfeffe55a40f3af38916f147cac0c7fe70a301ebd7a7ba3308f8eb86fa7baa6 972 main/installer-ppc64el/20150911/images/SHA256SUMS 50305f8f6a5ee7553e25f596d500c4fc6854d44897392ac00b6c03ee06780f31 576 main/installer-ppc64el/20151023/images/MD5SUMS 8296ee34584c6853b4718d68b1aca930466470613af840f26604876ad57093e2 972 main/installer-ppc64el/20151023/images/SHA256SUMS d0ff8c8255691028757777e5918e49581c2229962a9c74a35205b5720e9e369e 576 main/installer-ppc64el/20160101/images/MD5SUMS 7f59376f89488f4ba2cde49900a3770c3e36b18dce0b49ac76e47a9709d7f336 972 main/installer-ppc64el/20160101/images/SHA256SUMS 73f1744d28d9397dfeba4e644a6d8a5d5d8fd19c0ce2336063f2df4b966ea89e 576 main/installer-ppc64el/20160106/images/MD5SUMS b789bbaf626fa52e84a76d714b2af3cbdfb8fb3b9addd3a8b79d7473b6d86531 972 main/installer-ppc64el/20160106/images/SHA256SUMS 3b247fcbff136c542c34ed117423ff0a9fc4ba2d4925de62feacf13c1852e8ea 576 main/installer-ppc64el/20160516+b1/images/MD5SUMS 56ca9e6483a3e3e45d8521b0f25c114a0b165cd76f99340bf0d52a5d70b24039 972 main/installer-ppc64el/20160516+b1/images/SHA256SUMS 6c536a156954646d5a9b4613f319a2af5d22ad6133c28812f5fcbd711f624fb3 576 main/installer-ppc64el/20160516/images/MD5SUMS c4af2e8671e2a2e973e51cee17d82a7950e22d617d990c096e9db7a4e12a6975 972 main/installer-ppc64el/20160516/images/SHA256SUMS 2d3f61a311bcbfa4d628424fc1743b028e22f53f83d96baea4e083187880ad66 576 main/installer-ppc64el/20160630/images/MD5SUMS 976439ed51ae8ea69470581dd1ef4ee88c4fa305821530786d1be8bcce70a1de 972 main/installer-ppc64el/20160630/images/SHA256SUMS 2d3f61a311bcbfa4d628424fc1743b028e22f53f83d96baea4e083187880ad66 576 main/installer-ppc64el/current/images/MD5SUMS 976439ed51ae8ea69470581dd1ef4ee88c4fa305821530786d1be8bcce70a1de 972 main/installer-ppc64el/current/images/SHA256SUMS 376bfb191054107631fe8de2dcedcefa14b35a6e957a4210fe8b76a79a16471e 374 main/installer-s390x/20150422/images/MD5SUMS f8a4b1aaab7b502945db265c1560a47a641609753b77ed61587d68b3e0fd7218 674 main/installer-s390x/20150422/images/SHA256SUMS f5842aaa240147dd778c8db3b3bf957c76cbf7548bd2149582a11d1209561493 374 main/installer-s390x/20150718/images/MD5SUMS c28d1deedafad179325baaffa0c0f78a24b8a21bc0ea4dfcea01b54b89a0fd00 674 main/installer-s390x/20150718/images/SHA256SUMS 907f84b1f28a76b5fdb470f3e55f0571b3dcda80150d3dba7b74b198b641e1ff 374 main/installer-s390x/20150813/images/MD5SUMS cd0dd8b682a2902dabd5f9877670aa36a4bc054da19d22922cda7ddbd9bd334f 674 main/installer-s390x/20150813/images/SHA256SUMS 5a8f72684269197e6bf762a4358d29376df6f647019a566bf16c033a42320188 374 main/installer-s390x/20150828/images/MD5SUMS 32df3dc845ac26560573ac3aab101431e9951f531c53a6b03919146217067090 674 main/installer-s390x/20150828/images/SHA256SUMS 4a17edc1997b125da90951bbf25b1eacd48a1858864fa6d2de2bfc5b7862dfc6 374 main/installer-s390x/20150911/images/MD5SUMS 0d26154d6cb88e72612b3c5563202829fec6fe5c1812bdfdd12ad86819a35b20 674 main/installer-s390x/20150911/images/SHA256SUMS b490b3d5b51e989886c85cd99be29d09c19b58e754d7626cfd352d3141e988ae 374 main/installer-s390x/20151023/images/MD5SUMS e61867b0825e98dec6f4db39175bb1c76468697964ab430fceb27118bbd87abe 674 main/installer-s390x/20151023/images/SHA256SUMS d162662305450e61311ba4e674967ffdb475b909c5e2ed47fa41b1489cc79a6e 374 main/installer-s390x/20160101/images/MD5SUMS dd2b2f8c0c4fb2fc7fc19868d42da2342d21ae1952c24756f386277a57987677 674 main/installer-s390x/20160101/images/SHA256SUMS 58883dfbdd5b7941c6b4601da6f0fd27dc5f951a78a0782380e1551c08abaa56 374 main/installer-s390x/20160106/images/MD5SUMS f55533695eb1843741aee9dad3a9d9974870e49702929c88b148d692f774a0c4 674 main/installer-s390x/20160106/images/SHA256SUMS e298da017ad8fbfb0e2e8bf59c5fcd8d7ca825bd178eba110f89f5ca6044b92a 374 main/installer-s390x/20160516+b1/images/MD5SUMS cc731f7010dd8d07e572ee172c6cb9fb89a2f95876aae2eedb73e19a5bce1648 674 main/installer-s390x/20160516+b1/images/SHA256SUMS 4a37149f2de23ca21bb4d84c6c12624f24de81d37d57ec72f88600ce162ff861 374 main/installer-s390x/20160516/images/MD5SUMS f941bc95a52be3e8eb44a41c286e8b7dab0d6689f9471bd6336a0589fc5f7ce6 674 main/installer-s390x/20160516/images/SHA256SUMS b74a77a31313079a9e30f4d6c9240d623c417ca9bc28f997cc4e1715f4189ad0 374 main/installer-s390x/20160630/images/MD5SUMS f1bf9df36eec7aeadd4a945385f7961bc7245edc3b4a7926e4e836f16edeb6d6 674 main/installer-s390x/20160630/images/SHA256SUMS b74a77a31313079a9e30f4d6c9240d623c417ca9bc28f997cc4e1715f4189ad0 374 main/installer-s390x/current/images/MD5SUMS f1bf9df36eec7aeadd4a945385f7961bc7245edc3b4a7926e4e836f16edeb6d6 674 main/installer-s390x/current/images/SHA256SUMS 9476f882e92de56c32d5c1057241d2a23013a66384680922d4e65c68fbab3980 105 main/source/Release 8b72060cc35f189f55a1bf7f01d34f2a02f82ab0d21ac2e5dbd1e4e7e79f0207 35489733 main/source/Sources 5595454f6e710e828f13f69e994d5e2569b95c7082f8918f6b83e38b183514e4 27910 main/source/Sources.diff/Index 2ca55dff8b5bcd53c99457c9a6ab7089302025f78638bc5b9d25dbf1b832806f 9072408 main/source/Sources.gz da0be89f252019f12c2772b76f24e1d947b9f5ba8520fbe34ec2a8ddb8ae12be 6901228 main/source/Sources.xz 7b466e0293b45758508a090f33579a16584b0add1ec7fb9d7f553add26cfa3d7 14518404 non-free/Contents-amd64 d1e066e9180d9636424f01cf58f7183d0363a7bbd8c2524a8a005809f808ec3c 27416 non-free/Contents-amd64.diff/Index dfe9b4bf525d3b8c21a0ebc0fa8124b9ba89a21afec947fe60bcd88cedc0aaf1 812504 non-free/Contents-amd64.gz df9868d137f7f7a3e43e0e53bcfef8d9d7a9dcfaa962d0db53ae9407f9e3f92a 13465086 non-free/Contents-arm64 dcdd00f148198438d030a6cffa28b0ea35c125f9d5b5fbb5c683c28eefae79a9 19512 non-free/Contents-arm64.diff/Index 6cee186816f294b289c7f232a96bb4cb096c6467a09ff353d5901c8444efb8b7 731747 non-free/Contents-arm64.gz a6edf4cda478e2538b314b8dcfc6a6b834950fe9b378aba0e4974eb664a3def4 13478582 non-free/Contents-armel db82b93155c372f6d4aeaa641ddbf531a1c1c9d1b3c7da8bfbbc86bce5b42d39 20500 non-free/Contents-armel.diff/Index 4174fdd16f9cd2805b95b5b01fa67e887befc93cebb3914f6cfd74c1597244ad 733675 non-free/Contents-armel.gz 8e04746c8f7c7aa698e7895941d8bc4dcfc979862ee711fd1a17e35a52fa9cb7 13539201 non-free/Contents-armhf a5dc03511b0a5de95e1b2cbd5b6ad9ae9e0d9d172e90139c414157c8e89427ba 22476 non-free/Contents-armhf.diff/Index 827f9ae64d2e67734efa5a3fb8676ba4f3fb44663cc0c1d9ec109bf71f2c0d40 738525 non-free/Contents-armhf.gz 1ff8793a36b1a0db90af6efc38f80bd0758b225d03248eebfee9365cceb5ee0f 13374121 non-free/Contents-hurd-i386 1f136ee18b3ae63a19ac273dd3211b394a07e3ace9be04bd057de4be28d7b1bc 19018 non-free/Contents-hurd-i386.diff/Index e0e69f2ef25fd9c06208c580006d22d85da1090813dfa0805d36dd49434c68ad 724269 non-free/Contents-hurd-i386.gz 3febd7606c2fefad92049e6bc02e765faeaf282c62b9e63d0d7fa2845a5f0dc5 13755254 non-free/Contents-i386 0303a773478fc46a173f687bc8a6147d89b430f7e52e6581fc059b421918735b 23464 non-free/Contents-i386.diff/Index 6adbd1789477a4c9539d8353ae8b38e7764c293873dbae846a2e10ad0fc2774f 757556 non-free/Contents-i386.gz 741fab572d6cf9d1e34852082e8066ba7167b6a0cd98d0500406ebec34d8062c 13514206 non-free/Contents-kfreebsd-amd64 f5247cf283bd746f19283ba79cf8a42ca6f530710bd3e162e51f3286acdc2db4 19018 non-free/Contents-kfreebsd-amd64.diff/Index 9817601dd5d7429bd65c53e28fa5b9163ba17d02285d94d1a3de0c10aac9c024 736421 non-free/Contents-kfreebsd-amd64.gz e79b0a36ba3aad7f395611bf4fbde17e4441ae199b633684ff9e43b76cd9cba1 13515299 non-free/Contents-kfreebsd-i386 793e1143ca9af2a6f7adfca75a65aafab853a095ee0d6ba017f71ccba16c284a 19018 non-free/Contents-kfreebsd-i386.diff/Index 657b0c86081b1be93cc4b451e44da35cc534297aa0647191ee65756e37acd652 736493 non-free/Contents-kfreebsd-i386.gz 0d142d9255a6a6a9b9a3254e2a31050a97625208be9c680e810d84df7934be0f 13468449 non-free/Contents-mips 4084a98e2ab431fe43d73083bd8714c704a674ea2f9066341179fba5d8912801 19512 non-free/Contents-mips.diff/Index 03ce409381d582d0875d3deda19b066abb088bac5bd66cd17bd57210b176ed3c 732565 non-free/Contents-mips.gz 46215efab8e670ec09231851a47b21c30debc9763af9fde2289622583a971e0d 13465548 non-free/Contents-mips64el 50b2e568440f4ddab88577c6f04bd04f092861fc199e94453fccf4e06cc7bbd8 18030 non-free/Contents-mips64el.diff/Index d93ec2ef0dedbfc462dec55408b15ebb551c9e207ef0b84a97536083b128cc62 731477 non-free/Contents-mips64el.gz 73a05e461adcac92170eb10d519733fba7227a113121a5169cbb422ffd5e81d4 13479076 non-free/Contents-mipsel 95933911348a5bea482e3cf29c4bf7d9ddbf544fd10663febe10b9ffef05c7be 19512 non-free/Contents-mipsel.diff/Index bcaca5dc11a0a1f65a11cc878bf2a01249e0db0148d27f107c557363ec64d96f 733446 non-free/Contents-mipsel.gz f478ed38da7ba626a3db6ff70f354985fbbfa5bbc34bda70d1eae1481c9c397e 13467317 non-free/Contents-powerpc cd723abef7ccedb7fc32f97eaadb33c9f1432df55aa248adb50c8644f356b1aa 19512 non-free/Contents-powerpc.diff/Index 071e2b38e011051d2491aea3c99a58ee18ad58cb7b00b56daa39d839483e1124 732439 non-free/Contents-powerpc.gz 574b80334ffd304164db448054ef01cfe68ef960c2ae70c9b4c03b8890c63330 14067773 non-free/Contents-ppc64el e5f45bd5029265a6b2b04bb2185487af47c6f22d44db626d38708c3bbc24192c 19512 non-free/Contents-ppc64el.diff/Index 69c3ea08813c490034200d261814fd33b6864ffb9e2da0deae89b2069d541fdb 774292 non-free/Contents-ppc64el.gz 704ba4ff87dac7a8da5b76b50ff8755f7d480f28758f161d1e6194f5b2b03122 13475399 non-free/Contents-s390x 931eb1d031be7c97d082e89d5a62ba4ae7529a79c7c5819ad69c4d354889810e 20006 non-free/Contents-s390x.diff/Index a6958dffa25b6d2eb985d2aa7282e3bc486ed7f4f33f70728f8c7a1b78b84de5 733090 non-free/Contents-s390x.gz a210ee4eb96e6a1c0920c7c1305c2a04c3123098acef8ab203af955d35be8d85 8203337 non-free/Contents-source 5a61286838c2f021fccd6d2d8e8f6117f5ccf73cf8f11e206d29d94b0cf7fc35 27796 non-free/Contents-source.diff/Index 29daf88e88cc7a443818455ac3432505441681c64eee8fb0079c1e55b7382ce6 878132 non-free/Contents-source.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-amd64 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-amd64.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-arm64 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-arm64.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-armel 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-armel.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-armhf 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-armhf.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-hurd-i386 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-hurd-i386.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-i386 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-i386.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-kfreebsd-amd64 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-kfreebsd-amd64.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-kfreebsd-i386 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-kfreebsd-i386.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-mips 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-mips.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-mips64el 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-mips64el.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-mipsel 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-mipsel.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-powerpc 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-powerpc.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-ppc64el 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-ppc64el.gz 46cd40224a17d73f2128f9165814d5a8050dc3cf3b4a659581adf2148c2404cb 451 non-free/Contents-udeb-s390x 0cff97371dfefacdd754bb45d9e55f0c494158613fc46202ada07a93386a56ff 271 non-free/Contents-udeb-s390x.gz 4100d97c75adeb569fcdfff7aec147bc292062bd168a365703b06bc93f63ecbd 194055 non-free/binary-all/Packages 7d2aecac95ab2512ac91d40d97cb85e22cdb0fe7871b52aceaf459a8b20c74f9 52716 non-free/binary-all/Packages.gz 9dad80df850007b43edace6084987334801b5da517266b05b7c0ebd4177668fa 44872 non-free/binary-all/Packages.xz 51d50056fc0cb0e4394cad60c703bdac7c1a8643df381e7d011347be4b3ba13b 106 non-free/binary-all/Release 31afb60582d59780b4ce929dffe3e5b22533b981952304c97c8129428a485f4b 372384 non-free/binary-amd64/Packages ef49a05ceb3651f1ed050e8b0fa0a5cbe4646e86fd460b62d557493a6631e704 27796 non-free/binary-amd64/Packages.diff/Index 2475be32ba60366fb15d0d679e5bdd5d89211d153f967d8ec23921915be0bfe6 94091 non-free/binary-amd64/Packages.gz b9b76765cb3c02bbf69fb16d9f752419f95d9ede61983933a640df1697811942 78516 non-free/binary-amd64/Packages.xz d60bd5af7b9989c00aa24c2afa89d251f7ff5fc0bf9fa15e47afcea91adcd051 108 non-free/binary-amd64/Release ffddc03eec49bfbc2363a5ced1256c678cae4f4bad6dd515d8cb1eae66db093f 228434 non-free/binary-arm64/Packages f98c6d2889149a5e15080cd98c3e7c74b6d9791292fb6ba988f5d8deda19b58c 27796 non-free/binary-arm64/Packages.diff/Index 86368efe466ebde79711c8a2e002ba724d2727f5c5ae17534dc4bcaa6496343c 62112 non-free/binary-arm64/Packages.gz dec2a87e49d875553356c79c0a6a21ac30f78832afaeca6b2b40661c0f66aec1 52564 non-free/binary-arm64/Packages.xz 946c20f0df385f2d7233b2ce90460bd0894394e8b1bb6b2b00293223813d27b3 108 non-free/binary-arm64/Release 528cde6f11e2bf0572911b4efbe9ee21886d32e89646f8fb82a6da6a536c3da7 235109 non-free/binary-armel/Packages 5102efe50ebe046d3cc463031dff318ab14a3c7b6fde6c9aafef5077eede6f0f 27796 non-free/binary-armel/Packages.diff/Index d045de146a61d117a0aafae0cd404cbfbeb53bf84d90c6be493cfacfc33a8d8a 64174 non-free/binary-armel/Packages.gz c102d5df5a15505d3951895feb43d410bdef34d9394ed02ea4d0ea1c7781a000 54144 non-free/binary-armel/Packages.xz 9984e12504679bfbd364ebfef3ba6406aa0445b71b5b98f52567ca60b23dc656 108 non-free/binary-armel/Release c9a83eceb9f6007530993da64cd2bf00f22db724b3ee76889dd6268b5b8ccd49 275515 non-free/binary-armhf/Packages c28a57071ed9c7696f4e534ded5ae872706a85aec0013d32ab516599a54de91b 27796 non-free/binary-armhf/Packages.diff/Index cbefcdf70d1465762c62fc6aacd3ea3e652349b91fa1fc8e6e07fd4cc788231d 71048 non-free/binary-armhf/Packages.gz f9ddf6b29f02ff4142190106e3999fd756aa995cfedf2f95c6082a18923ccada 59664 non-free/binary-armhf/Packages.xz 4a0d4b3cce6c96e15e0111d7c66a6db69d4bf177a54553b7dc4e024f780bc2f1 108 non-free/binary-armhf/Release 5cd60593a1d15255b9424e3525ba5b08608ec8bd20f17d958ad1c80d40fce683 232894 non-free/binary-hurd-i386/Packages be52bd25199806cc2f88441a8ffff1726b6653c4aea91618ea6fa1d10bf4b203 27796 non-free/binary-hurd-i386/Packages.diff/Index 00860357838ea3b12f64e49125042d0cd1cb324951db980a99c3c8e0ce093626 62661 non-free/binary-hurd-i386/Packages.gz eb79813dc8bef64e642ad912e52d70e8dadd60cc27caf9b261b3eef1fd201dcc 53192 non-free/binary-hurd-i386/Packages.xz 881c495ebeb1c4eb5a95f394574a6114c2bc0f79b8730ca7c94b1a5d152211ac 112 non-free/binary-hurd-i386/Release c6ecce76604875f59e5eccd093540302b2d8365ebed9fed4d4c6f3804a3e29ac 337604 non-free/binary-i386/Packages d28bed36917ca34b84e41a180f438d0335902b370f02d73ab280ca1800b47ebd 27796 non-free/binary-i386/Packages.diff/Index c88d2c07afa95c9bd9ffcd7a037c6941a3686f6ff16980cd7f23e04b09f0167d 85001 non-free/binary-i386/Packages.gz 05e517cab2aa1eb7b475c7042df113ad58f7429eb8046bf3ab0577b21ea233b6 70972 non-free/binary-i386/Packages.xz 8dfb106459eb8e64fb45eb64cc9149575f3ede58182df83611126833f8d0e1ca 107 non-free/binary-i386/Release e782729775b3b87aab318a890433857faf6912531b05eca842e4fc6068023273 238159 non-free/binary-kfreebsd-amd64/Packages 0e5182638df8382789f119c448cba6a90256a7b930acde2d55ff4786714f4d25 27796 non-free/binary-kfreebsd-amd64/Packages.diff/Index fd9d8e7caa7d8ddc86c0c045be22bcb977e2fed06252fcfe5871e85f6553f215 64110 non-free/binary-kfreebsd-amd64/Packages.gz 802fe13e3c4efe2d508fe54a667388a6e253de46bc06065f9cc759a685f71ee7 54172 non-free/binary-kfreebsd-amd64/Packages.xz cf14ba1aa77c9bab4034aa54aa6b65c064aab1e21e83efd216b550e5dfb2f8ba 117 non-free/binary-kfreebsd-amd64/Release 2d101483ae233c09f62f1e81dcf3af439afd3f19e72510e232f0f92017912cb1 238774 non-free/binary-kfreebsd-i386/Packages e3a2c5555f233eaa81cc4b8e445f70a1c4628f9f6a8ece1a306a62e3f19f75de 27796 non-free/binary-kfreebsd-i386/Packages.diff/Index b413bc3cfd68b6a50b494d6ecc46ec68548e649b6a19d63ab022f3ac7dcb0b50 64166 non-free/binary-kfreebsd-i386/Packages.gz 8eff574bdf29ea4d897add8d8cddcad50ab393e8522dd4425c3bd48647be2c4f 54388 non-free/binary-kfreebsd-i386/Packages.xz 6d5ef61e0b5cd01d118249fe98aa27b6bde15b8d7a13c0ce0faf90f75a891270 116 non-free/binary-kfreebsd-i386/Release ce1873dbb986fc660704a90ccf32f9e7246f17b81116bdb8d7af6885d9c7412e 232072 non-free/binary-mips/Packages c55b6b1c99ed805832225c45b2a0f61030d4245b1ad326d0da1da4aa45f8f762 27796 non-free/binary-mips/Packages.diff/Index a531514c26f99ccce30136e76851be3575aef7a1f9b946f1d50c719c9c4cb1a0 62918 non-free/binary-mips/Packages.gz 439e13ad8a83d4d5ca579093d4b282b30d53783635a2e1bc07c421cdb36a26ea 53340 non-free/binary-mips/Packages.xz 143ca71226997dd2873eee4118fe26f3443f036fead6ff149c614e2db5f22202 107 non-free/binary-mips/Release b90d0bbb7c1a0f2d8d4b98be86dcaea60b31fc0cf478cb7da04cfe1c7a4765c5 229428 non-free/binary-mips64el/Packages d8732d7d6877521b04c90616980349bcfaf86a7d9bf687c297ca5083de1cac4d 27796 non-free/binary-mips64el/Packages.diff/Index 90eda650543dc7e647337ab44720c8c49a2ec851b4011d6d57a342eefb34c428 62084 non-free/binary-mips64el/Packages.gz 14d9dfa46ea0f85c0b933b7b21aee9dc40c5e0726692a6f2529c3f2cf609c3ed 52544 non-free/binary-mips64el/Packages.xz 8fbe42254ca8ac1b019a4fda52d912da4b93e95ae0c9eb04c7f4748d0bc50057 111 non-free/binary-mips64el/Release f804875d9c4efc3a5ae31f28aaf73c89eb30802d0949e8cc878482ef9ae7865f 235706 non-free/binary-mipsel/Packages 7386fde81da292b36599adea45e373aa519313f397140fa32a5f7bc641c9e825 27796 non-free/binary-mipsel/Packages.diff/Index f79838a5e4e4d2cf79abebb6c27cd77695373e78015ed1306d8a716c56921772 63921 non-free/binary-mipsel/Packages.gz e35ec9bf1969deb8f81a14b8859cafc090d9ead6e416ad2d088af42acce53171 54036 non-free/binary-mipsel/Packages.xz 32e889dd01e87d5bc03c0ef9bfc68601c2da6e777369be839f6833faf7586c05 109 non-free/binary-mipsel/Release 14a04b696178a51762c32a2e0e17c8b22686c1d334b15141f4255f7ddc42700f 231104 non-free/binary-powerpc/Packages 0443dcea310ea31f428851d281f4664cfc62263056dfc16b110cdbc749e141d0 27796 non-free/binary-powerpc/Packages.diff/Index 00c1c45b5ffab213413f780d808163dfde5573e8b1fd30453043bb23bc2d0dea 62821 non-free/binary-powerpc/Packages.gz 079d8ee2b944ba6a0407627933ef4b049a15e3c03e0bb3f37df816fc8d62db7d 53196 non-free/binary-powerpc/Packages.xz 2f69def9d89a278cfef84fd0e096d9f1ba890c128f9b6a40c9b6b71fe968af8b 110 non-free/binary-powerpc/Release 131dad26e72283d10abe76613438ace2bf68ea1c20eaa0e39e3576ba61ea39c1 255982 non-free/binary-ppc64el/Packages 2353851e1467160d0ecda93e72f892b2d1009797757e8feb6ee8014104e9983c 27796 non-free/binary-ppc64el/Packages.diff/Index 642496bde584ac91353c4e18870f21dd2c1bed5fbd8c73ccc32b3084130b5659 68178 non-free/binary-ppc64el/Packages.gz 380f53e5feb50fa52ae904a4b6f8480141706bc9dfcfe7ffbe938372a7d7cd4a 57476 non-free/binary-ppc64el/Packages.xz 970ba8cf785da4cdf0e7026d87608221d0aa6b0b4661de668a45bcab3a6bb9af 110 non-free/binary-ppc64el/Release 76c0086e000bb9708e4e0d307d307b6a1b98c8b75f1a1d50789b8c2421a06ebe 232449 non-free/binary-s390x/Packages 55bcfc0566e33955b96cc779c40837d5e40349b2c01b18133dcd6e120b7eb4e0 27796 non-free/binary-s390x/Packages.diff/Index 27ba2a8e2f933fe69b5301a048f98f046e29558ac03288a43f50c25018d54317 63088 non-free/binary-s390x/Packages.gz 986836565285be47ca418f6e4f1e6f9cc9a99fddc28ee407afe524b48e1d6e64 53436 non-free/binary-s390x/Packages.xz 952da0e4c619530fb52fb6a84da94ab5d9b10e103ff00929787bb521e338a194 108 non-free/binary-s390x/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-all/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-all/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-all/Packages.xz 51d50056fc0cb0e4394cad60c703bdac7c1a8643df381e7d011347be4b3ba13b 106 non-free/debian-installer/binary-all/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-amd64/Packages.xz d60bd5af7b9989c00aa24c2afa89d251f7ff5fc0bf9fa15e47afcea91adcd051 108 non-free/debian-installer/binary-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-arm64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-arm64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-arm64/Packages.xz 946c20f0df385f2d7233b2ce90460bd0894394e8b1bb6b2b00293223813d27b3 108 non-free/debian-installer/binary-arm64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-armel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-armel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-armel/Packages.xz 9984e12504679bfbd364ebfef3ba6406aa0445b71b5b98f52567ca60b23dc656 108 non-free/debian-installer/binary-armel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-armhf/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-armhf/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-armhf/Packages.xz 4a0d4b3cce6c96e15e0111d7c66a6db69d4bf177a54553b7dc4e024f780bc2f1 108 non-free/debian-installer/binary-armhf/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-hurd-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-hurd-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-hurd-i386/Packages.xz 881c495ebeb1c4eb5a95f394574a6114c2bc0f79b8730ca7c94b1a5d152211ac 112 non-free/debian-installer/binary-hurd-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-i386/Packages.xz 8dfb106459eb8e64fb45eb64cc9149575f3ede58182df83611126833f8d0e1ca 107 non-free/debian-installer/binary-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-kfreebsd-amd64/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-kfreebsd-amd64/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-kfreebsd-amd64/Packages.xz cf14ba1aa77c9bab4034aa54aa6b65c064aab1e21e83efd216b550e5dfb2f8ba 117 non-free/debian-installer/binary-kfreebsd-amd64/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-kfreebsd-i386/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-kfreebsd-i386/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-kfreebsd-i386/Packages.xz 6d5ef61e0b5cd01d118249fe98aa27b6bde15b8d7a13c0ce0faf90f75a891270 116 non-free/debian-installer/binary-kfreebsd-i386/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-mips/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-mips/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-mips/Packages.xz 143ca71226997dd2873eee4118fe26f3443f036fead6ff149c614e2db5f22202 107 non-free/debian-installer/binary-mips/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-mips64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-mips64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-mips64el/Packages.xz 8fbe42254ca8ac1b019a4fda52d912da4b93e95ae0c9eb04c7f4748d0bc50057 111 non-free/debian-installer/binary-mips64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-mipsel/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-mipsel/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-mipsel/Packages.xz 32e889dd01e87d5bc03c0ef9bfc68601c2da6e777369be839f6833faf7586c05 109 non-free/debian-installer/binary-mipsel/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-powerpc/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-powerpc/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-powerpc/Packages.xz 2f69def9d89a278cfef84fd0e096d9f1ba890c128f9b6a40c9b6b71fe968af8b 110 non-free/debian-installer/binary-powerpc/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-ppc64el/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-ppc64el/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-ppc64el/Packages.xz 970ba8cf785da4cdf0e7026d87608221d0aa6b0b4661de668a45bcab3a6bb9af 110 non-free/debian-installer/binary-ppc64el/Release e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 non-free/debian-installer/binary-s390x/Packages f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 non-free/debian-installer/binary-s390x/Packages.gz 0040f94d11d0039505328a90b2ff48968db873e9e7967307631bf40ef5679275 32 non-free/debian-installer/binary-s390x/Packages.xz 952da0e4c619530fb52fb6a84da94ab5d9b10e103ff00929787bb521e338a194 108 non-free/debian-installer/binary-s390x/Release d0f99061985c22fc085c6ae8eb3c1b49faeda978248b6dc9231251e07fc55d38 47445 non-free/dep11/Components-amd64.yml dec450f8372f0ba0292e6f59114d10d04de78aa3c1d0f905cdb60c31eb525cdb 7189 non-free/dep11/Components-amd64.yml.gz e91a6c938db083f3c72448e7d6a14588a8d8372026ec9da858918f05d2998c24 6624 non-free/dep11/Components-amd64.yml.xz 60c08380e7da73997e7fefef47aeae1cdf0d06eac41b8813c44afe23cbebf7f8 45122 non-free/dep11/Components-arm64.yml 947899ac45c47b076521e6390a29cb0703cd14e691ece7768823a2320bdf209b 6383 non-free/dep11/Components-arm64.yml.gz 8370528f52c99e8dad9505e8e0cb3051d86e01778501a5f7b522243296844894 5860 non-free/dep11/Components-arm64.yml.xz 8b7cc63f3c1a7f5138e2c13535c860ddab680f6321481c9a1d225b64e9ca6014 45122 non-free/dep11/Components-armel.yml 6d0000443aa725f3d62662c96049d7d96c67bd0cf132430e5c4e48d6a29143e2 6421 non-free/dep11/Components-armel.yml.gz aff035929971ae4118bca9cc2ecf87951270665db88be40545bf916d46feb627 5868 non-free/dep11/Components-armel.yml.xz 7c8f94dfed05924a841405c4e54638fa83befb07377ed52ac3f799db65f25808 45122 non-free/dep11/Components-armhf.yml 5f1f7c50a2457f181e7d6381cf9a99e5a0bea573610ee586e402eae2f911ab52 6463 non-free/dep11/Components-armhf.yml.gz d2ceb81fdd755aa22f5b2a32e82e4b4adabb48377d05875ad2c98db0b15dca1e 5884 non-free/dep11/Components-armhf.yml.xz fd3364d4ca33f527b0814355ff6d95bb3eeb1e56caf65c8c60017de8f46cea0e 47903 non-free/dep11/Components-i386.yml 707b8503d1752b4d82d09478590494c5b2d78591fbf75834ec9f8477292412bd 7512 non-free/dep11/Components-i386.yml.gz c8d50634540d21764ed49285171e58d31717dfc57849bce6ed1acd42a0d00837 6904 non-free/dep11/Components-i386.yml.xz 06e3abb8226856dd6655d842288920851c52cad5b644c885502157121d83e7e0 46201 non-free/dep11/Components-kfreebsd-amd64.yml af142b0fd62c51b911642891d4eaf203ac36022c99f5d05b03437b65dd233908 6927 non-free/dep11/Components-kfreebsd-amd64.yml.gz b8337441fc10262af8b3f68eabc24ced512cd2933a53404ea1e67ec8196647b9 6344 non-free/dep11/Components-kfreebsd-amd64.yml.xz c8fcfe26fa32623a4ade65c2fb740185cd488ed9f0b7eb26939901d0da0f1cd0 45122 non-free/dep11/Components-powerpc.yml 845f19e2cd67e13e23656fdfeb91e7353de66aa3e097bd40f87e3f14adbdfac7 6441 non-free/dep11/Components-powerpc.yml.gz 0a35a6fbabeac70a8a915e18946feea69d47a9c562598aac613dcbe2b1dd0739 5896 non-free/dep11/Components-powerpc.yml.xz 29e1afd7d3ecee0ca8926f94c1ef267374309fbea0315ce481cc94165d3b5790 30720 non-free/dep11/icons-128x128.tar 9aa465bbd41ea479173c3d49a216abdd64d7a7e945315d2d7316cb6cd21789de 20291 non-free/dep11/icons-128x128.tar.gz 3b7328ed6d22dccff7d283a2d72292dcce91b6f27d10d78033f37fb006359ce9 17920 non-free/dep11/icons-64x64.tar ec4198e6389982d54d353d63f7390352651d59acebadeb80b237d86400774e63 10022 non-free/dep11/icons-64x64.tar.gz 6fa6ff9f2b38fe64c81201a8fb73122f9725b00f3f43d553753cba01f7a3d5bc 374836 non-free/i18n/Translation-en 5f2db90b88c5c50154b27faf9cf308eb798268ae3cc38ef15beff9e2412e020c 79968 non-free/i18n/Translation-en.bz2 698511b9e33017225786d93c58b1fc531c4a1e3e615532617ed2d11e10c87656 25336 non-free/i18n/Translation-en.diff/Index 1fb81c024b1b640be3fdc17b17e9103eb7f7f712db540eea6ca59c24193ce8d6 109 non-free/source/Release 1f280627c948f7394f7aafded1aef1d8c0b3ebb78708928d6c4fc04c2e44fee0 344837 non-free/source/Sources a79903aaa72a8fc8f62f8813a44b1bccaa0bf690f17e30fb99b7975eab3d9e9f 27796 non-free/source/Sources.diff/Index 7719c8e965535f0df1f01a4c6bef2d05911ce17f3f5cc1a20b7f1c304ffa5934 98981 non-free/source/Sources.gz fab9e25c7264aff82e37039291a582d882550b2daa36881a572dfea00e56c0f5 82868 non-free/source/Sources.xz -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBCAAGBQJXmdEeAAoJEItIrWJGklVTTpkQALfUWL/coZ8EAVgE/YjDmGqQ o1wfpd5ffQFESPXVIFR4uJMlM/lmuST2+UB0DZB86qXESPHo56zXngPj3tDRV1tU xHbMtmZl/gLDmzISSDJ52+i+Ma8hAXUp3a1t+8QjSUf31OUPb40+mj6ft2aSJH4X 8juskoA/1v4VUCuGDiE1LD9EtrxJlGDAbh7h3xkbrp/ISwy9NC43sgsFOoEKip3m ZxkjgZ5VHFoKcSMgpjkkF/6kBhWHh7s4H8UA2LKpLPzIzuNNepLTQvWeFm/PMdcR k5kVtMTy3Vnx73wSbVblGZ6fNroO22AgAUCqk5u7oKGOn/A4cQqKxrpCvWVog1Fw wPicGkOELP1v9IsBiB24W4cBMN7vciHgssL8pgKCEn2SZVRT4SyofbwXgFckXYF5 VY11FFTXsfQXHn2o2E03sJkJ+nJIL1i6iiZXPrGfmg0lews9NXfloH3oLGobJpEd +T9X4NOWIFk8UyAvEuCQQZfkp9eQcXvhKR+Lmp4Zlc2+GcOZC+00vBlXf27hhhFF MdjwMGiTGxMFj+/CSTEMY9/86hk4W+HkDhCRFxsEd8HcCFEaPIjeEVSFi8RXbu8g YORq1kwuT4JlYA9GO1d2fMeNN2J1GJOunJeuvjXJ+sR1m7ybhxcMBYr30GsX/yQ8 XTd3OeBH1rfyPJIT8JFGiQIcBAEBCAAGBQJXmdEeAAoJEHY40EQrkNAQTpkQAJio 4zB+74XQpNoLpKSaebOmjW/GqlBbbex9j1t/84dgl34Gy7xeZ0PMTugCiYb0IipK fXYFoqij0g2n4/NWpyxNEFI0X+EWu+MgIAPAfFgZIbpJourKSc9NQPlDc3z4vLvW ylIZ0jxYfmwT/gaDw6c0Eq2eLcoi46UDnj1YdByrGfN47BXSzl2eMJbHwFuc9f9q 5XUSOMCPqcPqELUlCOmlp/858dE1ePCnaO8/IP8Dr48jpJhzaUtaJMdYxZ3mbog5 2mrCs6a9tn8QmkKTHZ+X5HwA7vgp9Hxt7rB2371ZnEdhUj6J3GsFSnQ52tzU9nKY 4AJbm+oK6o49dT3cO8EXFmH6z6F8lZXvAq112sA+5E6mLjhcQOMBuTZIB2l8Xav7 nkCtZFkDaHs8h1Tafs3xneMFU1N0zjirLWQ1DLakYZf74L2oyis2BLwFnKWyD7tn ns9VtiqgrWhCAAWDcLKCHOEVUuYV/7VgxvZHRiyK/SdUm3ajHYR2WqDckuuedcTe BHoUOiCQ9nVbhugYZBntFX8wKOHix3Tmp+JCnM4SWtwGNu/lwjZMqwIxvKY93+CR /D8cCVNvWplKPgmPz6jGRg31/R5Oq2HuMM5iByQOjk5dnXfy9oKBjtD0kB2Fa7Pe rWqOLXoUsaEsByI9NqinUBxI8duCg83YIrXZDY3u =+BFo -----END PGP SIGNATURE----- appstream-generator-0.6.8/test/samples/rpmmd/000077500000000000000000000000001320016272000212405ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/rpmmd/26/000077500000000000000000000000001320016272000214675ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/rpmmd/26/Workstation/000077500000000000000000000000001320016272000240135ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/rpmmd/26/Workstation/x86_64/000077500000000000000000000000001320016272000247515ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/rpmmd/26/Workstation/x86_64/os/000077500000000000000000000000001320016272000253725ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/rpmmd/26/Workstation/x86_64/os/repodata/000077500000000000000000000000001320016272000271715ustar00rootroot00000000000000359c4a0d13731581be86f571f3a672e82fe52f914f00929243f17c16da820326-filelists.xml.gz000066400000000000000000000101341320016272000424120ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/rpmmd/26/Workstation/x86_64/os/repodata[w:SxCjά4m愒 9/gQ%I#نpKRHc[۶_qT[z٪׀yܧ,j AD5}=R?',}lN Dgs}oIBiuTZK!/C ng ݠw 7vaoxmu{`kNE0a{4ND*$n@EF? VP 7ҹ?f^w1hN7'q)s`>d\[SOǧ'4ݔF~g]츃_\osZІA F}7v;~[l sxwC.Ƃ2%?%g'%ZPG\4bhPc3~8.%qBDŽc϶ޑ(Yq<_gU."6Ԥz2E4Rg*RTyW)h\F楖{rz=LP(͒OOǃ_^>N/PȽߟ.@>5fAKT0vC%oCWϒt2<7Җm:6r] J[X{+'uSs )׹?ޑ{=n&f?c?%|z3="d+ג9w㯳:Xq|v#۽;~mwZ?jۆΰKFx^;zꕆfd ;X8 [%ym9vxeg: _Y-7Jn7l+' #H47U\/n%01 1$v[ /@ioyP?|Ply~m&|z{楊F"a $f $cU8(S a+/͐-̿5M:^YXxtU@0Ÿ5i#Tp[#ΔY@*hiYBG7 p1za3tu8FľKH +vԱ9S=!W rx!6(Sd/ _ h}VEY+Q`5 Nzz0drqE6 切exs js=CN-~ic>[Dĝ鱖+rM\ْuA%&͓̿O̻խ`Vg ƸN(QRJP7U JĩnB'h|$|mhc({̎OpFA ,B?3j`CB &hPύ=LU9 0cwH3=iPAFsd1Jze;u a̔ӶΑb.*U7{k qؠ4([dS̱6t\`$ӓRjWGzň> ЃުqZ b*q<lMaM. pn fHn`0<艆jBMvR2X"Ogy>,Wc9Y.j 8Ⱥ9UaƽeУfb5'"=ϝ.*M& aNQ2ga].cަOJt0T~q3/=@?\u:Rkn(^tQa20c2@B~a:Bg%( )N9`=ϙHIR:j:s{N1|'؄?8[bNf W"3EP8n1pF&L{D5߉-eѼ4- d >68k=H#J>ric2IZC#Pֈ5 y^ g,"vFȟv֌AYX}bʟ\7~xPA#3[&!>0x 5 ( )-{ҫ0% VƩE^p~Y>ʭLAT#,}l,]>8^|-ՒeH:{$vnְ C7@kx@^wкF݁;jk&Ⲯ[if^2zYg\3Ӛ. 'BeݼD,3ug]ʜ\3ߦk% f\h_ag `t^Aג "ԥybfk1^O~;\,^6f+|/9W_.Owz|a=a|u37qffڒg'>;YG8n|57N{NbU9g5ws=oGL 7ÿO(>8.b߹ {ѠtAKoAv|~0r=uA]\yirdSG5{I^8;gw1봑f1fhNy˚shy7&$'<kzaCՇAuag}hI*==L4iQ6܈ZZ#oT=I|i#r% 0KGa=YUs+y$K\Vj騬ي b`omplu[t|reK QABmcmlc(o\&cǚA~Y<,ʄK[ySoiC*٬>T*>kO׆eMUHd#;zH=Aӆg,&ǞE 6-Y87ZgOhjx%<4_DXsȕ/\ {OЖ7DvYs-dre5yHpR|Z`! ڶ0me&j@lV}DTE\Ƶ担<4vWs~Bz*i볐ó;wi6ꦊ je~\4H8WN|>wʷLnjKmօ/kp>q>n%;z#ӻISkgiϺL͖m.evL ,h +fʬdt}@v=T鞺ݿ891148a3ce31e0695aa00ee72a7730e6978b049357956c81a605396453cc200a-other.xml.gz000066400000000000000000000013511320016272000414540ustar00rootroot00000000000000appstream-generator-0.6.8/test/samples/rpmmd/26/Workstation/x86_64/os/repodataKo6 a%I5^'-P=99ԪDA\a#}SVho¼ti<ѧЍxo._\|9ڏ˱8<}SU}7weXoVdYU}A&o\ h/ rJ zm"H6j)5UK*U-Qvсhdt 7MK F]Nt,[lB.UҶ/x/u) 2CdE?OnlO-qk>%4\O~H>mvp]_4lkr EOy`L֖ n)-.DZz/Xȩ:Y\#A(&Inq90VLIiF/4+ 墔Z)2eBD8>TE% Cc)75}ׯ@̈3!V:gtHL3fGI ^wh19i'4|,HN$vwY>,K&eVrzp GL`*C0on57Ls>>m-WЂ*s',Oӻu|? aE0I-ajak,)Ja{-.jCkTVBJ8!m petRT٦qWݣ^o$kGW VMbUݰ>!ZZ-2i'%+Zyb~8>3+U9p؋%kv Hq{깤Ѵ,D4a7(M};NLq , }}8\\-iI6ƗۅM5V,ctt򚬵O.T=OE%+:kt~MD#S O.CL5r-? !tqDzXۓ m PIdajP"Ў[gCꩻtƹW5LQ2r9{dh j*a:/aϿtLwKAb1)fR W KED6R'ƅCDYCآU( κ ,en&3Hk(wca IKb1 X 'UD(g?TusZ.h#UcCceU|b/998٧owdP.+n/#*Yd>k%lGҒ?]4f7M+3T$M)N<ؙ'~Dij ]+H+GM1=/"-zBZ-m!-5<j]y{S*"c70'?E뜖sI ^kVE8S~n 7$ub?W4ÙClVͶk;V<ͭwﻣͬbw};zv1>-HݐKV.'pHҹӣR}B{2}wQLy'&;ZC5XF^kp{^b 5unf5;\ٛ:+p.Y:e9ړ (@.z,O°-o@vr1$h'+s~c^0:_9ޡYyySGP}; U-LK/m{ ɚ>}$O\_) | Y N3sON!?{qݻK״W(CG20abEEKǘ;hC_Nr騚_&/3X3n(it]x uLa S,]'増s;ڞޛLIN8p'|+ 0~ o|=\ %QISߣn=igNVϯ3L{Ïá Z8BϷ"8B-0F{访F2z ޸Ԣ~PlTyo 49A%appstream-generator-0.6.8/test/samples/rpmmd/26/Workstation/x86_64/os/repodata/repomd.xml000066400000000000000000000030171320016272000312020ustar00rootroot00000000000000 1498315710 9e6f400df7895e52984c987d7fea543cc9ca9a87f43d5652a51f44241aaeb03a 98e300b6683be9c9e959ece52969ee32c0171cc9d922325c57af58ca2c9e4a65 1498315710 2285 9537 359c4a0d13731581be86f571f3a672e82fe52f914f00929243f17c16da820326 37006a808d524721a0e42ac402cffe6ef9c503478985569ec52bf0ed4315695f 1498315710 4188 49117 891148a3ce31e0695aa00ee72a7730e6978b049357956c81a605396453cc200a 84e64f9167328898522844619599d962dc33c3334c529b5bb512e85e850a0f1b 1498315710 745 2499 appstream-generator-0.6.8/test/samples/table.svgz000066400000000000000000000314001320016272000221210ustar00rootroot00000000000000~uFtable.svgz}moFgϯ|R(#cbv{͐oR$~KDgQTVuh+*dD~/VWo./: W˳7}uQ9xu}srqvbw_Wv:YWɻի?y?owǟ::~y_իWi/x5]~<oNn. N~NWoW߯.n hVח?\^`Z(k#ccG׿~ʈx<|W-g}͋Yyᖽ<[/Wp9o_?|ypvsQiƋWNNW*8y=(՛^oξ:`?_C5+v+GB}\'u~upW'W7?^^nuq|zPHPPɷoW0=wW7Goޮg;c77ߜz]]?w-M/O÷_ί?`A)yurf8٣N/߾]'?]?ܩ?v=s\v?8J堐77?}A<BtJL7o\eZ5ϔ^k2}ZqW!nAxُU[:;77C`zu׋_Yzbu՛C7<&Car|_@3푟 0ՆsaMm`qFs ʖO}SwXIB"t,1) SF٢ɸ-'|?۔5۟HE0QWG|X@JHDH$J 'Xq>wV 43oGSkyOA0d-O<)3bMp@\(!zxD .6A,J9{6z<wp<D9CB*=A+^sL9Z[A!VRa(r{ڐ0&lJvMWG0T ZVq $IKx| Wd< ׌M2 q;ٰW̹1cL_>c *4-R fgG3*LC4XޚP5Ù&E^)˔,UShUS&qtfVUB8hg3*2&IH-o 5*BKa4Ǡ& jQ*,,=P´Qˀ` nl.㾁#2L"ޡ>y,/V= = 8>/4DeЖxחVJ-ЊР:(NkL4HذS;T)9ג/eXT[UU~ Y<ЫΘJu~ἫVAӝLE= TP(yj<<Hd7^~ "nw$#Ul-`4{Y~nZve?~|3|_0Xh`&JFpB5j."(6_60 ?}EQFC",woYH&TP p7D@ȤGT L)C,,d\ˣt]"Ѥ\miWzVL4-]|oON"B8g @.[mҖơq8"&v"[D/k 2Y}k6!3 |?V E|%-菫K]!͟[}DH+4kXq6nS=s|;=kDImM;JYZY ʅO&KXsb<Yd_,?Ah-Xh=҂=~œ6onV q3g< B̙ %G4xc#e##csٺ!0X8L-6\#5&жv+B;-V RР% J$!4}˔֠ `Rƺ ٜffm6:oTfx;e4 x( 8]zڦQ9C^L?P A)lYã=wspu%JDu4Kɋնª8Q0bhdMlN7mfQѢv떠$:(T 9˖{3 u dY xQmGYYAG ICI̥ YU&SD__bS-;8gdn):m7Ч%pz2XZB\{) ᤈ@GYͶI;uJ-Y=q[DSg]ڳ7GחGBHS0"U'FSq(su@푍c&VCn՞οOߠތ ؤsQwEJ#KMy:=y^L4Nb[`v"l1MMJER46ZMcڴk0M\. ) "B;:!01<HbASC18׫XK id5=9Lo$\",/n 4^_ E#\SMٮ0B9dp%AQ2O8Ju91BffWmfқ@ J=1tgpA 8#piD;% i$K&30!8P2TOL;B8vR!"CM,ը襔Fhcp ;&66b4F ;,P$c'BQR̀#J 'Y|"E\B`'[%>jM5bwobs:'d 'zlg+r$E7?Ncn 4%ٚ90TClϩ8z={">׳d@ĚNj@e3U6+wkEd6^Z^/IHR[ Lr#*7~3hO=X<үN\)D>\,xHrM.a{(?Q{l)Krdž4ޙ󤴁o/6nFOKMmcwKi#O|${f(!I7MW(Ke6n/gFV} /&[) );> ߧgjg̖Q,A3/0krl>VhmOkh} 1EˉټuI\tL's^ЦF^~8 ID?\;iJ";N|ڂ?hCr Drk1^ ]R~dC"E=~.IU/wF;la*Es @j|d XJML I:~ @Bp*Q XQj)vhf~U !^LK 1Dsu作`_'dN*t/T<.@vL^E@*1jhuhDT]Otuw FXlWN|E 홚|रq%ܹʜcE,Ϣ/ụ&-`ڤS0mR),d0-iOIͧ`ڤS0Xd0OIͧ`ڤSXdZNOSOӢNSQu=aģmÏɷc@u퀎e)hJIY0 #tܖ,VuӷM7Z:G!wn.=\ҥŵywoBrZ4ƾJ eNpj 8z,"=,=l:3 ImtRekG~gl2ᇸfݜipyil\ \C3<|~s?R yom fKVI{R´Uؿ}=nO R ߓŠ:o)4ia[8&_Ǹ=),¸Y3/gkVE>PRdK@KH@D3K[=aUǸ=-lKY*+uܞ[ ˦qܞH]PS7eܞ&J[ fa\b¾i hF?ۓq[a(lj SZte[ Ea8rKa ^2O}9՛.[޾8oVgfuqb on}q||q 'g߮?{y!\^>.+[?}%p0xE:|wߝo33GӣbC0r"iqʬE̖tiDҔ,jZEcsX4iV˖ugB>l?>BJ[,˗ti0hb. ִktK4s}NP.r-̅7RS diU,\[HՔ3of~^4a` PJ1O eݠ$c0R!cn .^a ~:vsQИ1!h)yxT)VKȐ:%dv- m9QS*gPК@K푉պbfg5p FD Nť-sz&R@XRӻOlj؝LM`,!?WHTCMA,ҷSOl63FfkӘ hMPеȶ&}>::&v)vDb2 "^{ 0#uѡl#<\|9aw/˦HziTJ,hD#"$ 97JrHQH4 4 i#5i;}4$ Ήdk=DִuP TcطĴ.~L1KG>g G͚'DLJJI!myV>^1R}ay>O0(&'XR:}ܤ.#F(`cȘ _rx6}dcBmئrAn>' 3p}!rfk"O>{ϯӎǭ}Q^jG9nH@!%BHif{O͕wecR*xRS,/3 YJJhG pJ zNf:#!7-uލ88!Pekj e#6= : md{dm@r@ES ( ՙ(nYI$m@,Q* GسW6=  OPD~C*jH v Ȁ3 6 ) p6j$wC栊jHڀ.1 a4c\Cm0&Q3(\r6$ۀ|@1k7m(K(@M k]R+Y6] Hvz6@զ .BmOj v !(76ܩ9Xj]>L8R VSEU@T:P G@jݠZt6S<+LM8M 6 ĨQaPr6= v !$ 6 % + Yd6= HvC!m` w4UݪE6Zhb YR6= w Lj (w 88p]mzIP% ),MrզNSnTm:qf1pEhFAZ;6= Hw Hqk@6= H:9PG]&,N%բ pG%b զ @%ۀ >j) H KTmzElC"=!s;a6jHڀ.D\2^SmzQP2iBG3=Xtl>EyA-j(ڀl! 3 6 %P n զ.I-.$WmzQ!U@m@;&eU@;r,pEf@%UТ[A#M<OĈ-$IDvjb.,([Дnښ6_r^+TkmWRJN:!(r-1BNl-,2Y"Mhjcx86>͜ &34sM.6Wf< `a`j`X5ʌ:2,QhL1C3^['Oe:V8w1H S8iwKr$9ʌ9PnLm]'-4*1G!lLЂ ǟfe:>hٝ+th46J "R>s $~{MIdasQef?=mx< Ȍi]z~Jgˆc9O'8f1s,2k:aVy#l<>ĀBF-iβh{PF@}WLA{pyӚģˎ2)vF72GUg+a)ҔAl 2o2sʴ=jS&&>{ZKmx- ~x~XoGc P4>;U߻>O>:@e6߳'Ϟ=DF&l 0&&'LIT+2.Dhd6cw@LJLqH4ǸxZĘh &-wÂYfc l* Sai&1|Bd#'s MD[dAx>3L֐ ֡Ne.I4'餇9z $ƃ Pf--ʝʴzEe>:m%pm=;!"NiE2D[7E[ =)N){z`Gbz.rrڃLTxiS5m]9s2|"lSAvd|X5kK봃Su9ď:tG 9ݣ=Ȳ3vmIzz`1vNݧ:@PqrI@bNO0뀎S#Tu@:qEkj e1܎Ւ&;2-mRbL/| 1&ÃdzI lʊ4]O9}6la˦1?n~%ς6!i=yROH,HNqHrĜahLII=%eX&g@eD5NZ&P- ǷyFvzW 6*Nw[<5;ddlJ2ّkݪ!'gqNfgԉU5'z짾@aϬH2ܾ1X7@?d$?nQDf2M tA'PmjfDˁ<~Ŝ&y )\<gNDcB z>{z(p&6'.="[,Rcۆីᶹֺ1|ZiÚ둣qѮz˫Wo//z+.onvo.n<~R]2oncx7'?^]޿4uW{X{W߼{_W}#v[ǺVpWIw >oR.5]+{ JM6}Wjɧi\.RELj8^4,Mz~FX3ŸaXPj}$%ՌОZǵƘ5sIiB ;%22s΄S hp]'a11z{revl)0f&>$  ŗ~~A V&#[2f֣y'|wuh|u_E%E}5CS tGu 5?; F.;B!yB HEywX f(F^z_3mݭ{!1ȩڹQ3}jĶ5\ 3Z {W`7O5w›˫wݿoޞY^p=߽<-S?_-N˛K'ɮPVUz ޏ](^S "`aŚ)v=>y)57?߾_yysM w?r{|yӞW.7/ _k"zhF8+q\ (zl{kQiss[[Oot_3].2n&jI'dUU2W @R Ç8T =dX ĩbR>XnWZO?jw%lUrY|Q]By2ϯzP>(x)aC䴍]^_mvwߗ'{vsY6kViҒEeMoZ^zQ/.p8TyM׀F:.3A^rDn[bGB Dg1P ixO2X lK w9iQOZDq[o_/~jݥB/w|r7Wooo.:'=y]Kt66S9@XI)x(X"U/(lƍG~0va!&Ww﮻np6 1Y|= m/Wvi2 S!&[t؈T#8poHH9@ĢYht5* ącEا0{Y_"*bE-A6Rۖzp6~}$٨GWӑ>jP <Ux̠ZbOɪZnOӡ&>WJUS1Ǡ,TRK"aI,-"%ʡE}U*)ehRkjY& 1ffofΓXQB%8T*+퐊੹r>ARUƴJUQa[Q8XGШ#&k_=40eNhnH/ lXԏ- HP $S6tFUINHk ڲ!s/D@j.GGC" QԸV2Jb!F5D 01V樅Q*tLC Gxb +QkDBXF8bďM(vo/F9SY!RJCo-a>KƐHT>t.\M`z8vpVb+kmQriKlL(z Y21gA VW35̬.U'Y(s9U4k~SuG&_~T_.!quA `Iih>ݸ$) h},u aŋ:Cpw4>maR8':.8<(S=i Ϻ%-i(Ĥ Юى*je_#B"iD8i iZI|` % F ĘliI=HaIxH\)JMat#PqEC/)lV gFn%}Єv-OQ4Xӳҙ@IS-iz`B<6s ҙ pa &֓pn ݆½&&߷6 դI} ťxG(R)+i3@%q–,e!E (1Dӝ*`Vu +!pU bdZMpg[ѐ2Ho0RU 2u00%Bč:ZeDDž!2PVZJ[O Jԅ(j2֪6ҋZIE׭1;ZBNP`HP:T̟!."]BR8 9WrHQ&45\XX!C^(>4Ci iVaD0q)D_WH*Q5J`.x!4Z0^~"#.PԜ*IWؗz ք済eWD 0/1{Ju:=t(V4SIoRm{JYiw(+W38i$bT=\9)zr.̱ܵ-{GVJ@4j=pufq6[}IU$;0E15j< %P)%6dcRΒuhFٶ= KWoV#BCH{7QDLՃWgEd,Rq%v B iZkVQrYQb}3#^@=lǛ2.! =!kOr{ʿީ d݉OoȞe?\1sš hڅPJA\d<0 =p yn`>\L,⠩fOʡӇ_g3{Q9 p<<<9dsc$7̈=vy}pԬSu[9ے\qnK]5sSn8VRWߔ\׊DWmKMKUnKǾRuҞt[riܖ=٦pVDn'=OmiSm޷p[:mZsn˞CpSn8V۲0۔\׊ɲ-6-[-pvikc),dkܔkvu݈NVLYI%8+lappstream-generator-0.6.8/test/samples/test.tar.xz000066400000000000000000000240001320016272000222440ustar00rootroot00000000000000b/0000775000175000017500000000000012757035064010314 5ustar laneylaneyb/a0000664000175000017500000000000612757035064010453 0ustar laneylaneyhello